React Router - undefined params if previous one is not defined - javascript

This is how my routing looks like:
<Switch>
...
<Route
path="/search/:searchValue/:who?/:industries?/:area?"
component={Search}
/>
...
</Switch>
Then I've this link (in another component)
<NavLink
className={classes.appBarLink}
to={`/search/${input}/${chiCerco}/${industriesSel}/${geoArea}`}
>
I'm filling those data in to="" with a form.
In the next page I'm catching the data with:
this.props.match.params.who ... and so on.
Problem is, if "industries" is empty I'm not ablet to get "area".
So I've to fill all the data, all the time.
Is It correct?
The params are actually "optionals" in the URL.
(also the URL from this.props.match.url is incomplete if I'm not filling all)
Thanks a lot.

Related

How to navigate between two pages in React JS

I am using React-Router-Dom to navigate between two javascript elements in a create-react-app dapp but when I use it loads the elements on top of the page and just adds the page to the end of the link (localhost/page).
My goal is to have the page reload to the new page on click of the link button with a new background and styling (already done for that page)
App.js Code
<Router>
<s.Screen>
<Navbar />
<Routes>
<Route path="/MyPandas" element={MyPandas} exact></Route>
</Routes>
/*
Rest of Code
*/
</Router>
My other page is just wrapped in a Fragment Component
<Fragment>
/*
Code
*/
</Fragment>
use exact in your Routes e.g : <Route path='/products' exact>
Assuming your links are working correctly, and it seems they are if the URL in the address bar updates to "/MyPandas".
The issue is that the element prop isn't passed a correct value. react-router-dom#6 Route component's element prop takes a ReactNode, a.k.a. JSX, not a reference to a React component. Pass <MyPandas /> instead of MyPandas.
<Route path="/MyPandas" element={<MyPandas />} />
Note: There's no need for the exact prop. Not only does it not exist in the RRDv6 Route component API, but all routes are now always exactly matched.

Accessing data passed from NavLink after redirecting from home page to a specific page using react router

I am working on a react web app and i am using react router. I want to pass data from the NavLink to my Movies component. The NavLink is shown below.
<ul>
<li id="movies">
<NavLink exact to = {{pathname: "/", state:{page: 1}}} > Movies </NavLink>
</li>
</ul>
In my router, i want to redirect to movies/all/1 from the landing page. My routes are:
<Route exact path="/" render={() => <Redirect to="/movies/all/1" />} />
<Route exact path = "/movies/:genre/:genrePage" component = {Movies} />
In the Movies component, i can access the route parameters but i am failing to access the data, {page: 1}, passed from NavLink via location props. I keep getting undefinedas the value of props.location.state. How do i go about this? I don't want the data i am passing to be in the url.
EDIT
Perhaps to clarify. The question below partly answers my question.
ReactJS - Pass props with Redirect component
However i am still failing to access the data passed from Link when the page is first loaded and then redirected from root path / to /movies/all/1. It is only accessible after Link has been clicked.
Redirect component doesn't pass location.state to the next route (i.e /movies/all/1).
If you want to do that, you need to get location.state from your Route / and pass it down to Redirect.
It would look something like that:
<Route exact path="/" render={({ location }) => <Redirect to={{ pathname: "/movies/all/1", state: location.state }} />} />

React-router.Nested routes

How to make nested routes???
I want initial route to be course/:course_id? after that, when i click on a node I want my url to become course/:course_id?/nodes/:node_id .
I use : "react-router-dom": "^4.2.2"
return (
<Router>
<div id="app-main">
<Header />
<Route path="/course/:course_id?" component = {Content}/>
<Route path="/course/:course_id?/nodes" component = {Content}/>
<Footer />
</div>
</Router>
);
When i click id redirects me to course/nodes and skips :course_id
return(
<div className="paragraph-text-child" onClick={() => this.props.select(chapter)} key={chapter.node_id} >
<Link to="nodes">{chapter.text}</Link>
{this.iterate(chapter.nodes)}
</div>
);
I think you have some concepts mixed up... Route is for handling received URLs, Link is for setting it.
Link does not know about Route, Route does not know about Link. Link sets the URL to what is specified in to. So if your current URL is /course, and to="nodes", the result is /course/nodes. If it was to="0/nodes", the result would be /courses/0/nodes.
Now if I understood correctly, you always want a number between "/courses" and "/nodes", correct?
This can be achieved with Redirect, which comes from react-router-dom too.
If you create the following Route:
<Route path="/courses" render={()=> <Redirect to="/courses/0"/>}/>
And rework the previous route so that course_id is NOT optional
<Route path="/course/:course_id" component={Content}/>
When you navigate to /courses, you will be silently redirected to courses/0. The result is that your Link component with to="nodes" will always redirect to courses/number/nodes - because effectively the courses/ location won't be reachable anymore. Every URL that would not contain a course_id, will be redirected to course_id = 0
Note that these 2 routes should be put in a Switch, and in the correct order, otherwise you will end up redirecting every time...
I have not tested this, but it should do the job:
...
<Header/>
<Switch>
<Route path="/course/:course_id" component={Content}/>
<Route path="/courses" render={()=> <Redirect to="/courses/0"/>}/>
</Switch>
<Footer/>
...
And this should handle /course/course_id
Now, if you want to nest a /course/:course_id/nodes/:node_id Route, that should go into the component rendered by the parent route.
Let's rework our parent Route into this:
<Route path="/course/:course_id" render={(props) => <Content ...props />}/>
What this does is, instead of just rendering the passed component, it renders the component and passed down Router props. Which means that the rendered component will be able to handle routes!
Now, in the Content component:
render() {
return <Route path="/course/:course_id?/nodes/:node_id?" component={NodeContent}/>
}
The last thing we need to do is change the to property of the Link component so that it will redirect to the target node:
<Link to={"nodes/" + chapter.node_id}/>
Does this make sense? I may have missed some gotchas in your code - the idea of what you want to achieve is in here, but you may have to adapt it a bit...

How to replace a react component with react-router

basically im rendering this react component:
<Grid>
<Him className="him"><Link to="/him">Him</Link></Him>
<Her className="her"><Link to="/her">Her</Link></Her>
</Grid>
essentially just 2 boxes with links to him and her.
I have this route that correctly renders my Categories when you click on him.
<Route
path="/him"
render={() => (
<Categories
products={products}
addToBasket={addToBasket}
/>
)}
/>
However it renders this component underneath the him/her components. It might sound silly but how do I get it to render them over the top or instead of it?
I could something where I set the state of the component to visible: false and toggle that but that seems a bit messy.
all the stuff in this tutorial: https://reacttraining.com/react-router/web/example/no-match, seems to have them routing via header that never disappears, whereas I want to click on links in the body of my application and then show different content. any ideas?
You have to wrap the Grid in a Route as well. You could do something like this
<Route path='/' exact component={LinkComponent} />
And somewhere else in your code:
const LinkComponent = () => (
<Grid>
<Him className="him"><Link to="/him">Him</Link></Him>
<Her className="her"><Link to="/her">Her</Link></Her>
</Grid>
);
This way, if you go to the home route, you see the Grid, and when you click on a Link, you go to corresponding route and the Grid will be hidden.
Ok you just wants to replace the entire content when click on /him or /her, so as Xander Berkein said you should render your links into a main component and then assign it to the / main route, y that way you need to use exact prop to just render that first path that matches to the URL, so
<Switch>
<Route exact path={‘/‘} component={<Links/>} />
<Route exact path={‘/him’} component={<HimComponent/> />
<Route exact path={‘/her’} component={<HerComponent /> />
</Switch>
I hope you find it useful.

React-Router Questions/Issues

I've decided to use React-Router to manage the routing of my Meteor JS App that uses REACT JS.
I've gotten React-Router to work 'somehow', but it is having some negative side effects that I would like to explain here, in the hopes of finding a solution.
First of all, here is my code:
if (Meteor.isClient) {
Meteor.startup(function () {
console.log('startup');
Hooks.init();
const {Router, Route} = ReactRouter;
const history = ReactRouter.history.useQueries(ReactRouter.history.createHistory)()
React.render((
<Router >
<Route name="home" path="/" component={Sidebar}>
<Route name="managedata" path="managedata" component={ManageData} />
</Route>
</Router>
), document.getElementById("render-target"));
});
}
and in order to navigate between those two routes I've used the Link component provided by React-Router:
<ReactRouter.Link className="item" to="/">
<i className="home icon"></i>
EXAMPLE
</ReactRouter.Link>
<ReactRouter.Link className="item" to="managedata">
<i className="block layout icon"></i>
Manage Data
</ReactRouter.Link>
This is the problem:
1.) Upon loading of the homepage which has the "/" as the path, I am getting random characters showing the URL. This is ugly especially since one would only expect "/" or just nothing to show in the url aside from the domain name or localhost....
e.g. http://localhost:3000/#/?_k=q2c52z
2.) When I click on the Link to 'managedata' I am also getting some random characters in the URL
e.g. http://localhost:3000/#/managedata?_k=6clzfn
Here are my questions:
1.) What is causing those ugly characters to show up in the URL and how do I get rid of them?
2.) Does Link only use the path value? As you can see above, my homepage has a name "home" but a path of "/", I've noticed that if I change the Link to Link to="home" then I get directed to a URL with a "home" on the path which seems to be incorrect.
3.) I ended up using 'component' above as one of the props in Route. I've noticed that many of the examples on the internet uses 'handler'. However, when I use 'handler' in my code.....it doesn't work.....
How are those different?
4.) I've defined my routes as above, but when I use the page does not render initially, but if I click back button on the browser and then click the forward button, then it renders. How do I solve this?
Many hours ago I had the above problems.
Now I've found the solution and I'd like to post it here in the hopes of saving some time for future readers who bump into the same problem.
Here is the Q and A:
1.) What is causing those ugly characters to show up in the URL and how do I get rid of them?
As per https://github.com/rackt/react-router/blob/master/UPGRADE_GUIDE.md
"If you do not specify a history type (as in the example above) then you will notice some unusual behaviour after updating to 1.0.0. With the default hash based routing a querystring entry not defined by yourself will start appearing in your URLs called "_k". An example of how it looks is this: ?_k=umhx1s. "
So add 'history' into the Router.
e.g.
const {Router, Route, IndexRoute} = ReactRouter;
const history = ReactRouter.history.useQueries(ReactRouter.history.createHistory)()
React.render((
<Router history={history}>
<Route path="/" component={Sidebar}>
<IndexRoute component={Dashboard} />
<Route path="managedata" component={ManageData} />
</Route>
</Router>
), document.body);
Notice the history={history} inside the Router.
2.) Does Link only use the path value? As you can see above, my homepage has a name "home" but a path of "/", I've noticed that if I change the Link to Link to="home" then I get directed to a URL with a "home" on the path which seems to be incorrect.
After reading and experimenting....
The value of 'to' should be the path.
Not only should it be the path, it should be the path surrounded by {}.
For example, for the route defined above the Link should be used like this:
<Link to={"/"} className="item" >
<i className="home icon"></i>
EXAMPLE
</Link>
<Link to={"/managedata"} className="item" >
<i className="block layout icon"></i>
Manage Data
</Link>
The surrounding {} made an important difference for me.
Otherwise the page would not render initially....I had to click back and forward again on the browser for the page to render.
3.) I ended up using 'component' above as one of the props in Route. I've noticed that many of the examples on the internet uses 'handler'. However, when I use 'handler' in my code.....it doesn't work..... How are those different?
https://github.com/rackt/react-router/blob/master/UPGRADE_GUIDE.md
Based on the above link, it is the difference between the old API and the new API.
4.) I've defined my routes as above, but when I use the page does not render initially, but if I click back button on the browser and then click the forward button, then it renders. How do I solve this?
I've answered this problem in the answer to number 2.).
But basically, for me, I added {} around the path and it started to render properly.
e.g.
<Link to={"/managedata"} className="item" >
<i className="block layout icon"></i>
Manage Data
</Link>

Categories