How to use routes in React? - javascript

I created a web-app that uses reactjs. Now the basics of the app are :
Create Topics/Sub topics.
Display them (this uses react )
Now 2nd task is explained as :-
Show all the topics/sub topics list.
Clicking any of them sends json req and the data is recieved and displayed.
Now I want to share the topic with link , however on clicking any of the topic only one elemnt of the html renders and the url remains the same.
So this is what i want to do -
On clicking , send json req and recieve data ( done )
Change the url ( I want to know if it is possible using the same react page? )
How can I use Routes in the following code ?
Part 1 :- Deals with recents posts
Part 2 :- Deals with the Headings or Topic names
Part 3 :- Deals with Sub topics
Part 4 :- Deals with showing the Article from the chosen topic and sub topic.
Now its obvious that though the article is displayed , the link / url of the page will never change. However it makes it hard to share the articles. Thus I want to know how to apply the routes in this case ?
render() {
var lists = this.state.list;
var lists2 = this.state.list2;
var aname = this.state.article.name;
var date = this.state.article.date;
var lists3 = this.state.listrec;
return (
<div className="row">
<div id="recentsbar" className="col-md-3">
<div className="row">
<div className="col-md-9">
<div>
<div style={{ display: this.state.hide2 }}>
<h2>
<b> Recents </b>
</h2>
<div
className="lds-ellipsis"
style={{ display: this.state.load2 }}
>
<div />
<div />
<div />
<div />
</div>
<div id="subl">
{lists3.map(number => (
<Item3 name={number} show={this.rec.bind(this)} />
))}
</div>
</div>
</div>
</div>
</div>
</div>
<div className="col-md-8">
<div style={{ display: this.state.hide }}>
<h1 style={{ marginLeft: 6 + "em" }}>
<b> Subjects List </b>
</h1>
<div className="row">
<div className="col-md-6">
<ul style={{ marginTop: 1 + "em" }} /*className="list-group"*/>
<div
className="lds-ellipsis"
style={{ display: this.state.load }}
>
<div />
<div />
<div />
<div />
</div>
{lists.map(number => (
<Item name={number} hide={this.hide.bind(this)} />
))}
</ul>
</div>
</div>
</div>
<div className="col-md-8">
<div style={{ display: this.state.show }}>
<h1 style={{ marginLeft: 6 + "em" }}>
<b> {this.state.selsub} </b>
</h1>
<div className="row">
<div className="col-md-auto" style={{ marginLeft: 6 + "em" }}>
<ul
style={{ marginTop: 1 + "em" }}
className="list-group art"
>
<div
className="lds-ellipsis"
style={{ display: this.state.load }}
>
<div />
<div />
<div />
<div />
</div>
{lists2.map(number => (
<Item2 name={number} hide2={this.hide2.bind(this)} />
))}
</ul>
</div>
</div>
</div>
</div>
<div style={{ display: this.state.showarticle }}>
<div className="lds-ellipsis" style={{ display: this.state.load }}>
<div />
<div />
<div />
<div />
</div>
<div className="arthead"> {aname} </div>
<div style={{ float: "right", opacity: 0.5 }}>
Updated on: {date}{" "}
</div>
<div
style={{
marginLeft: 1 + "em",
lineHeight: 2 + "em",
marginTop: 4 + "em"
}}
dangerouslySetInnerHTML={{ __html: this.state.article.body }}
/>
</div>
</div>
</div>
);
}

You should look into react-router's Switch and react-router-dom's Route Components.
For instance the following jsx:
import { Route, Link } from 'react-router-dom';
import { Switch } from 'react-router';
class YourComponent extends Component {
render() {
return (
<Switch>
<Route
path="/"
exact
render={
() => (
<h1>root content</h1>
<Link to="/content1">content1</Link>
)
}
/>
<Route
path="/content1"
exact
render={
() => (
<h1>content 1</h1>
<Link to="/">root</Link>
)
}
/>
</Switch>
);
}
}
Route allows conditional rendering based on the URL.
Switch ensures the first matching Route only will be rendered (actually what's returned by the render prop of the Route component).
For all of this to work, remember that a Router component from react router must be an ancestor of YourComponent.
If you want to trigger an SPA navigation after an event, or during a callback, you have to use the withRouter HOC from react-router.
StackOverflow thread explaining how it works: Programmatically navigate using react router
I also suggest you look into react-router-redux for redux integration of react-router. It offers the push action to navigate to another route.
References:
https://reacttraining.com/react-router/web/api/Switch
https://reacttraining.com/react-router/web/api/Route
https://reacttraining.com/react-router/web/api/Link
https://reacttraining.com/react-router/web/api/withRouter
React : difference between <Route exact path="/" /> and <Route path="/" />
https://www.npmjs.com/package/react-router-redux

I have created a Simple react routing example, hope it will make you undrestand routing in react.
https://github.com/shivakumaraswamy/reactjs/tree/master/ReacRouting

Related

Change state for each button individually

I have a button to show details of each card in my react project like this. the amount of cards are unknown and it is based on what I get from API.
just like this, I get the data and I'm mapping it:
<div className={styles.contentCardContainer}>
{factorList !== undefined && factorList.length > 0 ? (
factorList.map((list, i) => (
<div key={uuidv4()} className={styles.contentCard}>
<IconButton
color={showListService ? "error" : "success"}
onClick={() => {
setShowlistService((prev) => !prev);
HandleFetchDetails(list.ID);
}}
sx={{
display: "flex",
alignItems: "center",
alignSelf: "flex-start",
}}
>
{showListService ? <RemoveCircle /> : <AddCircle />}
</IconButton>
<section className={styles.eachSection}>
<img src={doctorImage} alt="doctor" />
<p>{list.Doctor}</p>
</section>
<section className={styles.eachSection}>
<img src={calendarImage} alt="doctor" />
<p>
{list.Date}   
{list.Time}
</p>
</section>
<section className={styles.eachSection}>
<img src={RialImage} alt="doctor" />
<p>{list.Payable}  ریال</p>
</section>
<section className={styles.eachSection}>
<img src={discountImage} alt="doctor" />
<p>{list.discount}</p>
</section>
{showListService && (
<DetailsListService listDetails={listDetails} styles={styles} />
)}
</div>
))
) : (
<Alert
variant="filled"
severity="warning"
sx={{ justifyContent: "space-between" }}
>
<p>There's no data</p>
</Alert>
)}
</div>
</div>
as you can see, I have IconButton element that I mapped it so each element have this button. but there's a problem.
I just have one state.
just like this :
const [showListService, setShowlistService] = React.useState(false);
since the amount cards I will receive is unknown. I can't define multiple states, because I don't know how many I should define. this is a bad practice too.
so whenever I click on IconButton, state changes for ALL buttons. how can I make it work individually.
change state for just a button in that specific element
Create a component for the cards and each card can keep the state:
factorList.map((factor, index) => {
return <Card key={index} factor={factor} />;
});
const Card = ({ factor }) => {
const [state, setState] = useState(false);
return <div>Your card stuff here</div>;
};

”Warning: Function components cannot be given refs.“ error while using custom component in nextjs [duplicate]

This question already has answers here:
Warning: Function components cannot be given refs
(7 answers)
Closed 8 months ago.
I have a HeaderIcon component that looks like this:
function HeaderIcon({ inactiveIcon, activeIcon }) {
const [isActive, setIsActive] = useState(false);
return (
<div onClick={() => setIsActive(!isActive)}>
{isActive ? activeIcon : inactiveIcon}
</div>
);
}
export default HeaderIcon;
When I run my code I got these errors:
Unhandled Runtime Error
Error: Hydration failed because the initial UI does not match what was rendered on the server.
Error: There was an error while hydrating. Because the error happened outside of a Suspense boundary, the entire root will switch to client rendering.
And I checked my console and saw this:
Warning: Function components cannot be given refs. Attempts to access this ref will fail. Did you mean to use React.forwardRef()?
This is where I used my HeaderIcon:
function Header() {
return (
<IconContext.Provider value={{ size: "30", color: "#374957" }}>
<header className="flex items-center justify-around py-1.5 px-3 bg-white">
<div className="flex items-center space-x-2 w-full max-w-xs">
<h1 className="text-4xl">Zipp</h1>
</div>
<div className="py-2.5 px-4 flex items-center">
<InputGroup>
<InputLeftElement
pointerEvents="none"
children={<SearchIcon color="grey" />}
/>
<Input
type="text"
bg="whitesmoke"
w={"full"}
focusBorderColor="none"
border={"none"}
placeholder="Search"
/>
</InputGroup>
</div>
{/* right */}
<div className="flex items-center space-x-6">
<div className="headerIcons active:opacity-80">
<Link href="/">
<HeaderIcon
inactiveIcon={<AiOutlineHome />}
activeIcon={<AiFillHome />}
/>
</Link>
</div>
<div className="headerIcons">
<HeaderIcon
inactiveIcon={<MdOutlineAddBox />}
activeIcon={<MdAddBox />}
/>
</div>
<div className="headerIcons -rotate-12">
<HeaderIcon
inactiveIcon={<AiOutlineNotification />}
activeIcon={<AiFillNotification />}
/>
</div>
<div className="cursor-pointer">
<Avatar w={7} h={7} />
</div>
</div>
</header>
</IconContext.Provider>
);
}
Since you are adding a Functional Component inside Next.js's Link tag, there are some changes to be made. Here is an overview of what the say in the documentation:
If the child of Link is a functional component, in addition to using passHref, you must wrap the component in React.forwardRef.
Which means, first you should add passHref prop to Link when using HeaderIcon, this way:
<Link href="/" passHref>
<HeaderIcon
inactiveIcon={<AiOutlineHome />}
activeIcon={<AiFillHome />}
/>
</Link>
Then change HeaderIcon to the following code. Notice I'm using useRouter from Next.js to handle active and inactive state.
import { useRouter } from "next/router";
const HeaderIcon = ({ onClick, href, inactiveIcon, activeIcon }, ref) => {
const router = useRouter();
return (
<a href={href} onClick={onClick} ref={ref}>
<div>{router.pathname ? activeIcon : inactiveIcon}</div>
</a>
);
};
export default React.forwardRef(HeaderIcon);
function HeaderIcon(props) {
const [isActive, setIsActive] = useState(false);
const { inactiveIcon, activeIcon } = props;
return (
<div onClick={() => setIsActive(!isActive)}>
{isActive ? activeIcon : inactiveIcon}
</div>
);
}
export default HeaderIcon;
I hope this will be helpful for you. Thanks

Animation I created with spring is not working

The codes I wrote for spring are below. My code is not working even though there are no errors.
export default function heroImage() {
return (
<div className="heroImage">
<img className="sliderBackground" src={Background} />
<Spring
from={{ opacity:0, marginTop:-500 }}
to={{ opacity:1, marginTop:0 }}
>
{
props => (
<div style={props}>
<div style={sliderContentStyle}>
<h2 style={sliderH2Style} lang="tr">En iyi Yerel Lezzetler Menzil'de</h2>
<p style={sliderPStyle}>Taze kuruyemişler, Sağlıklı besinler ve sofralarınıza lezzet katacak baharatlar için Menzil'e gelin</p>
<img className="sliderFoto" src={SliderFoto} />
</div>
</div>
)}
</Spring>
</div>
)
}

How to style React component after importing

I did some research but also I didn't find a proper answer
import Card from "./components/Card/card";
class CardCollection extends Component {
render() {
return (
<div>
<Card />
<Card />
<Card />
</div>
);
}
}
export default CardCollection;
How do I style** those Card components?
I tried:
<div className="class-name1"> <Card /> </div>
<div className="class-name2"> <Card /> </div>
<div className="class-name3"> <Card /> </div>
But I think it's not the good way to do it.
Neither this
<Card propName="margin-tb-20" />
<Card propName="margin-tb-20" />
<Card propName="margin-tb-20" />
<Card propName="margin-tb-20" />
<Card propName="margin-tb-20" />
Even doing this by using the loop does not look good for me. So is there any alternative?
First of all, you must provide component name capitalized:
cardCollection // Rename it to CardCollection
Now, to your query; you can provide props to the component:
<Card className="class-name1" />
And in the Card component, you can provide the props:
{/* card */}
<div {...props}>
eways to do it:
1- via passing inline style:
a: <Card style={{color:"red"}} />
b: inside of card comp you can use it like:
<div style={this.props.style}>
2- by class name:
a: <Card cssClassName="c1" />
b: use it on every element inside of card like example:
<div className={this.props.cssClasName}>
note that if Card comp is a component that you import from a library you should read it's document instead, normally they implemented both ways

How to make images fit the page in React/Bootstrap?

I am using a function that maps every item in the props array to creating an image tag. I am trying to make every 3 images have a row div around them using bootstrap so they will fit the page correctly, but I cannot figure out how to do it. Any help would be appreciated. Here is the code:
import React, { Component } from 'react';
import "./Skills.css";
export default class Skills extends Component {
static defaultProps = {
images: [
"https://upload.wikimedia.org/wikipedia/commons/thumb/6/61/HTML5_logo_and_wordmark.svg/1200px-HTML5_logo_and_wordmark.svg.png",
"https://upload.wikimedia.org/wikipedia/commons/thumb/d/d5/CSS3_logo_and_wordmark.svg/1200px-CSS3_logo_and_wordmark.svg.png",
"https://upload.wikimedia.org/wikipedia/commons/6/6a/JavaScript-logo.png",
"https://p7.hiclipart.com/preview/306/37/167/node-js-javascript-web-application-express-js-computer-software-others.jpg",
"https://bs-uploads.toptal.io/blackfish-uploads/skill_page/content/logo_file/logo/5982/express_js-161052138fa79136c0474521906b55e2.png",
"https://webassets.mongodb.com/_com_assets/cms/mongodb_logo1-76twgcu2dm.png",
"https://www.pngfind.com/pngs/m/430-4309307_react-js-transparent-logo-hd-png-download.png",
"https://botw-pd.s3.amazonaws.com/styles/logo-thumbnail/s3/012015/bootstrap.png?itok=GTbtFeUj",
"https://sass-lang.com/assets/img/styleguide/color-1c4aab2b.png"
]
}
photo() {
return (
<div >
{this.props.images.map(image => (
<div className="col-md-4">
<img className="photo" src={image} />
</div>
))}
</div>
);
}
render() {
return (
<div id="skills-background" className="mt-5">
<div id="skills-heading" className="text-center">Skills I've Learned:</div>
<div className="container">
<div className="row">
{this.photo()}
</div>
</div>
</div>
)
}
}
CodeSandbox
I think, I found the issue,
<div> <-----This div is the issue
{this.props.images.map(image => (
<div className="col-md-4">
<img className="photo" src={image} />
</div>
))}
</div>
You have wrapped your col-md-4 with a div, and div has display: block style, so you are getting every image on separate row. Simply replace div with Fragments,
<> <-----Make it Fragment
{this.props.images.map(image => (
<div className="col-md-4">
<img className="photo" src={image} />
</div>
))}
</>

Categories