I've had two routes:
<Route path="/client/:id/members" component={Members} />
<Route path="/client/:id/members/:mid" component={MemberProfile} />
why when I'm trigger:
window.location.href = `/client/${id}/members/${mid}`;
then my url is changed to correct form like in the route path but not redirect me to MemberProfile component?
Thanks for any help!
as
<Route path="/client/:id/members" component={Members} />
declared before
<Route path="/client/:id/members/:mid" component={MemberProfile} />
and
/client/${id}/members/${mid}
fit
"/client/:id/members"
Members component will still be rendered.
Consider one of the following:
decleare MemberProfile before Members
change MembersProfile route to /client/:id/member/:mid for example
use exact Route property
Given:
<Route path="/client/:id/members" component={Members} />
<Route path="/client/:id/members/:mid" component={MemberProfile} />
It seems like you are rendering these routes into a Switch component. Remember that the Switch component renders the first child <Route> or <Redirect> that matches the location. This means that route path order and specificity matters.
Order your routes by decreasing specificity. "/client/:id/members/:mid" is more specific than "/client/:id/members" and should render higher in the Switch.
<Switch>
...
<Route path="/client/:id/members/:mid" component={MemberProfile} />
<Route path="/client/:id/members" component={Members} />
...
</Switch>
Additional note
You may want to avoid using window.location.href to redirect as this reloads the entire page, and thus, your app. Use a Redirect component to render a declarative navigation, or use history.replace(`/client/${id}/members/${mid}`); to issue an imperative redirect.
Related
There may be a better solution here than using regex, but not sure how to go about it.
The issue is that I want my navigation component that lives in a component called MainLayout to show on all routes except on /login & `/logout
Currently, I have the following 3 routes
<Route exact path="/logout" component={Logout} />
<Route exact path="/login" component={Login} />
<Route
exact
path="/:subdirectory?/:nested?/:id?/"
component={MainLayout}
/>
So navigating to /login or /logout will render either Login or Logout and also MainLayout which is understandable with the current setup.
However, is there a way to use regex (or any other means) to check that if /:subdirectory is either /login or /logout then do not render component?
<Route path={${process.env.PUBLIC_URL}/book-repair/:name/:name} component={Modals}/>
<Route path={${process.env.PUBLIC_URL}/book-repair/:name} component={Companies}/>
when call second route this is calling very well. but when am call first route first route and second route both are calling. please solve my issue.
Use Switch to render the Routes Exclusively and use exact to strictly match the pattern
import { Route, Switch } from "react-router";
let routes = (
<Switch>
<Route path={${process.env.PUBLIC_URL}/book-repair/:name/:name} component={Modals} exact />
<Route path={${process.env.PUBLIC_URL}/book-repair/:name} component={Companies} exact />
</Switch>
);
Refer: https://reactrouter.com/web/api/Switch
<Switch><Route path={${process.env.PUBLIC_URL}/book-repair/:name/:name} exact component={Modals}/>
<Route path={${process.env.PUBLIC_URL}/book-repair/:name} exact component={Companies}/> </Switch>
You should add exact and Switch to your routes.
If you are rendering the routes into a Router they both can be matched and rendered. The Router inclusivley matches and renders routes. Use the exact prop to exactly match one or the other. The issue is that ${process.env.PUBLIC_URL}/book-repair/:name is a prefix for ${process.env.PUBLIC_URL}/book-repair/:name/:name, and so will also be matched.
<Route
exact
path={`${process.env.PUBLIC_URL}/book-repair/:name/:name`}
component={Modals}
/>
<Route
exact
path={`${process.env.PUBLIC_URL}/book-repair/:name`}
component={Companies}
/>
The alternative is to render the routes into a Switch to exclusively match and render routes. Here path order and specificity matter. Order your routes from most specific to least specific. You don't need to specify the exact prop since the Switch only matches and renders the first matching Route.
<Switch>
...
<Route
path={`${process.env.PUBLIC_URL}/book-repair/:name/:name`}
component={Modals}
/>
<Route
path={`${process.env.PUBLIC_URL}/book-repair/:name`}
component={Companies}
/>
...
</Switch>
I tried to Routing the params ":id" in react with a sub Route ":id/history" and the route link not render the component on clicking
<Switch>
<Route path="/patients/:id" exact component={GeneralData} />
<Route path="/patients/:id/history" component={History} />
</Switch>
The Switch component renders the first route that matches the URL you entered
Because you are using a wildcard for your GeneralData Route like so
<Route path="/patients/:id" component={GeneralData}/>
No matter what you enter after /patients, it gets captured in that wildcard definition of that Route because it accepts literally anything. So even if you navigate to /patients/4834834/history it still satisfies the GeneralData route which was found first in the list of routes.
To fix this, simply move your History Route above your GeneralData Route. This makes it so the GeneralData route will not get rendered for anything that just satisfies /patients/:id. Switch will look to see if your URL matches History first.
<Switch>
<Route path="/patients/:id/history" component={History} />
<Route path="/patients/:id" component={GeneralData} />
</Switch>
I think you're omitting exact param.
I am creating routing for my react app, could someone explain me difference between these two approaches.
From user point of view they work the same, what is the difference in performance, best practice?
First one is multiple Routes rendering different component for the same path:
<Route path='/:shop/booking' component={Services}/>
<Route path='/:shop/booking' component={Calendar}/>
Second is single path rendering components as props.children(?) :
<Route path='/:shop/booking'>
<Aux>
<Services/>
<Calendar/>
</Aux>
</Route>
<Route path='/'>
<Component>
</Route>
Is equivalent to :
<Route path='/' children={Component}/>
According to this : https://reacttraining.com/react-router/core/api/Route/children-func :
Sometimes you need to render whether the path matches the location or
not. In these cases, you can use the function children prop. It works
exactly like render except that it gets called whether there is a
match or not.The children render prop receives all the same route
props as the component and render methods, except when a route fails
to match the URL, then match is null. This allows you to dynamically
adjust your UI based on whether or not the route matches.
So by giving children prop instead of component to your route, you force it to render even if the current URL does not match. And I might be mistaking but it seems that adding a component prop to a route override its children prop.
Thus you cannot expect the same behavior for this two pieces of code :
<Route path='/:shop/booking' component={Services}/>
<Route path='/:shop/booking' component={Calendar}/>
Shows the two components for the specified path.
<Route path='/:shop/booking'>
<Aux>
<Services/>
<Calendar/>
</Aux>
</Route>
Shows the two components wrapped in another, for any path.
Finally, I would say that the best practice in React is to wrap your two components into one, and add it to the component prop of a route instead of creating two routes with the exact same path.
If you cannot wrap your two components because one has to be displayed on several routes, you can use something like the following :
<BrowserRouter>
<div>
<Header />
<Switch>
<Route path='/' component={Home}/>
<Route path='/foo' component={Foo}/>
<Route path='/foo2' component={Foo2}/>
</Switch>
<Footer />
</div>
</BrowserRouter>
I am trying to implement a routing structure where a user goes to another user's page or their own when the path is /:username. I also want to render another page with a path /watch or /watch/ .. Facebook has a similar setup where /:username will take you to your page or another user's and /watch/ for example is a page. Is there best practice to achieve this with react-router?
As of now I have something like this..
<Route path="/" exact component={authenticated ? Home : Index} />
<Route path="/watch/" component={Watch} />
<Route path="/:username" exact component={({match}) => {
if(match.params.username === data.Username) {
return <ProfilePage match={match} />
} else {
return <UserPage match={match} />
}
}} />
Now if I got to /watch/ the profile component is being rendered aswell. So :username is going to match all my routes?
As you already deducted, /:username is matching at the same time as /watch/ because both patterns match the URL /watch/.
Thankfully, React Router provides a <Switch> component for cases like this one, where only the first match is rendered:
<Switch>
<Route path="/watch/" component={Watch} />
<Route path="/:username" component={...} />
</Switch>
Now, with the URL /watch/, only the first route is rendered, even though the second one matches too.
If you are using react-router-dom v6, do these:
instead of Switch, you should use Routes
instead of component={<SomeComponent />} property, use element={<SomeComponent />}
Just in case, you can Read this article about upgrading from v5 to v6