Using multiple params with React Router? - reactjs

<Route path="/:user" component={Home}>
<Route path="/:thing(/:version)" component={Thing}/>
</Route>
So, I've got two dynamic objects in my application that I'd like to be controlled by route params in react-router. Using the code above, both /0 and /0/3 take me to Home. I need /0/3 to take me to Thing. I'm not sure what I'm doing wrong here... Does react-router even support multiple dynamic params next to each other like this? I couldn't find anything in the docs.

What happens here is that you've given React Router two paths that can both match on /anything. By default then React Router matches the first one it can find.
To dig deeper, if I go to /pudding, React Router can't know if you meant /:user or /:thing. Since /:user occurs first, that option will be chosen.
You also need to make sure if nesting routes is what you want. Currently, your Thing route is nested below Home, which means that it is rendered via this.props.children in your Home component. So, for your current Thing route, Home will always be rendered too, with Thing as a child. If your Home component doesn't render this.props.children, Thing will not be shown.
I suspect you just want two different pages. What you could do to achieve that is the following:
<Router history={history}>
<Route path="/user/:user" component={Home} />
<Route path="/:thing(/:version)" component={Thing}/>
</Router>
This will make every /user/name go to the Home component, and every other /random (with an optional extra level) will go to Thing. If you wonder why in this case React Router doesn't take /user/name to the Thing route, it's because it still matches in the order your routes are specified. Because your Home route matches the requested URL, no siblings of this route are tested anymore.

Related

React component not rendered when sub path is called directly

I am having a Server Side Rendered React app where I use HashRouter for react routing(v5). My Routes look like this
<HashRouter basename="/">
<Layout {...config} />
</HashRouter>
<Switch>
<Route exact={true} path="/" component={LPComp} />
<Route exact={true} path={this.props.siteBanner.Red} component={bannerPage} />
</Switch>
When I hit localhost:8888/parent/ and once it get loaded and if I hit localhost:8888/parent/banner in the same window the bannerPage component renders fine.
But I hit localhost:8888/parent/banner directly(consider in a new tab), then the component is not rendered properly.
Any ideas why this is happening?
Also to add on when I hit localhost:8888/parent/banner I can see LPComp(default route) also being loaded and then it disappears suddenly and the bannerPage component renders improperly.
Thanks in Advance
The behavior is making sense, since your routes is based on a prop/state this.props.siteBanner.Red. So the first thing is to put a console.log once you enter this component.
console.log(this.props.siteBanner.Red)
In your first case, you reach this component from its parent, this way the props mostly likely is resolved.
In your second case, you reach it directly, of course also from its parent, but most likely there's no time for the props to get resolved quickly. Couple of possibilities
useEffect is to update this variable
mouse click is required to get a value
setTimeout is used to defer
callback is used to get this variable
You can say there's 50ms delay in getting this prop resolved, but you need to dig out why yourself. Dynamic route is more advanced thing, it's easy to have permanent route.
Thank you all for your timely response, I was able to solve that issue by setting location=(req.url) from the server side configured static router. Going through this example I got the bigger picture I was missing.
https://medium.com/javascript-in-plain-english/server-side-rendering-in-react-redux-ab0af31c9c4b

React-router matches wrong component with similar match

So I am developing an app in react and have react router lib to show different possible URLs in my app. I have the following routes, defining which component will be rendered, depending on the URL:
<Route path={`/products/:address/:page`} component={Products} />
<Route path={`/products/:productId`} component={ProductDetails} />
<Route render={() => <NotFound/>}/>
The 1st one expects something like this: /products/store/1 to match the products and show the products page.
The 2nd one expects something like this: /products/5e996d123e1e0816242aed80 and shows the product details.
The 3rd one is a fallback UI, if nothing matches
My problem is, that if I am in the 1st URL and delete the page (1), eg /products/store/, react router gets confused and tries to match the 2nd route.
In both components, I load the params incomponentDidMount like this:
this.props.match.params.address, this.props.match.params.page for the 1st component and this.props.match.params.address for the 2nd.
Ideally, I would like to render the 3rd route, if the 2nd argument of the 1st route is not present.
One possible solution would be to change the 2nd Route from /products/:productId to /product/:productId, so it won't get confused.
Is there any better solution for this?

how to have the same route path hit different components

I'm having an issue with react router and its routing path.
I have a couple of links, say
localhost:3000/a
localhost:3000/b
localhost:3000/c
and my route is set up as so:
<Route exact path="/:cat" component={Post} />
My issue is that whenever I go to one of the three URLs, i.e. 1 -> 3, it will only load page 1, as all of them meet the criteria (i.e. path="/:cat"). Am I correct to assume that it won't render each path as they are referred to as ONE route, hence it doesn't need to be rendered as the "state" hasn't changed?
Its one route and any matching path (/a or /b) will render that Post component.
<Route exact path="/:cat" component={Post} />
This route will allow you to render Post component for each url, that starts from / and this component will have the actual url inside this.props.routeParams.cat.
You can use this prop in your Post component to call the appropriate child component. i.e Check if this.props.routeParams.cat = a , then call <ComponentA />.

ReactJS Values In The URL Always Visible

I have a filter system for my products in ReactJS which basically has the following:
http://localhost:3000/category/women/subcategory/tops/sorting/null/price/null/size/null/color/null/brands/null/merchants/null
The Route is as follows:
<Router>
<Route path="/category/:cat/subcategory/:subCat/sorting/:sorting/price/:price/size/:size/color/:color/brands/:brands/merchants/:merchants" component={Products} />
</Router>
The Problem is that I want to show filters in the URL in when they have a value other than null. Current my component works but I have to display every single filter in the URL with a null value by default, this is causing my URL to be extremely long. The only way I thought possible was to do a permutation combination of all the possible URLs in the filter and direct them all to { Products } which is extremely silly. There must be something in the Router component that I'm missing?
You need to use optional params in this case.
As and example if you want to accept both sorting/ascending/price and sorting/price you can write your path as follows assuming you use react router v4.
<Router>
<Route path="sorting/:sort?/price" component={Products} />
</Router>
You can read more about this here: React Router with optional path parameter

React-router child-route navigation not working

I'm trying to follow the react-router tutorial here trying to navigate using a child route and it doesn't work.
For example given this route definition:
export default <Route path="wifi" component={ Wifi }>
<IndexRoute component={WifiView}/>
<Route path="list" component= {WifiListView}/>
<Route path="connect" component={WifiConnectView}/>
</Route>;
If we are on "/" and navigate to "/wifi" we are good. The WifiView is presented however if if from "/wifi" we call hasHistory.push('list') it doesn't find the route. I would assume that the route is relative to its current location since I'm not using the "/" but that isn't being respected.
Also the document said:
You can also use the router that Router provides on "context". First,
you ask for context in the component, and then you can use it...
But I don't see anything that mentions how to do that in TypeScript so I'm using the static hashHistory.
It looks like novice questions but I had nowhere to ask since the suggested Discord channels are all dead... Can anyone help with those?
Thanks! Appreciate any help!
Ok finally found the replies to my questions...
As for today, react-router don't support relative navigation which means, it hast to navigate to the whole chain of routes and that is why hasHistory.push('list') doesn't work.
In order to get the context.router we need to use withRouter high order component but that isn't exposed on the TypeScript definition files they provide.

Resources