I'm trying to figure out why passing a param using React-router-dom's Link and Route is not working correctly.
My routes are configured this way:
App.tsx
<Routes>
<Route path="/:id" element={<Home />} />
<Route path="/search" element={<Search />} />
</Routes>
Home renders data using a default initial ID, And I am using Link inside the Search component to send an id param to render data in Home using this different id, this way:
Search.tsx
<Link to={`../${idParam}`}>
<li>
Some Link
</li>
</Link>
What I expect: when the URL points to '/', the default Home component should be rendered. When a param is added Home should receive this param and be rendered using the id sent.
However, currently Home will only be rendered when an id is provided as a param (for example: '/1234'). When navigating to '/', React responds with 'No routes matched location "/"'
Appreciate any help clarifying what's wrong with my set-up, thanks!
Now route matches exact path by default. Uptill v5 we could declare a parameter optional by using a question mark symbol(?). But unfortunately its no longer available in v6. Ref - issues
Now instead of optional parameter, you can declare children routes under a parent route. Use the code below in App.tsx
<Routes>
<Route path="/">
<Route path=":id" element={<Home />} />
<Route path="" element={<Home />} />
</Route>
<Route path="/search" element={<Search />} />
</Routes>
Also change your code in Search.tsx to
<Link to={`/${idParam}`}>
<li>
Some Link
</li>
</Link>
Related
I create a react website My website
Please check my website for more understanding
https://fastnews77.netlify.app/
On the blog page, I added two nested routes
<Route path="/blog" element={<Blog />} >
<Route path="" element={<Allblogs />} />
<Route path=":id" element={<Post />} />
<Route path=':tagVal' element = {<TagPost /> } />
</Route>
The first Blog component render
Blog title
the second Allblogs component render
All blogs
then I used 2 nested routes
Post component for individual post
TagPost components for tag related all blogs
But when I click any tag it will render the Post component of any random blog
what i add in tagPost component
const { tagVal } = useParams();
check this link for code
Github Code Link
Please suggest some code or reference for this problem
Yes, you can nest routes with dynamic path parameters, but you can't specify two route paths with the same specificity. react-router#6 uses a Route Ranking system. The path pattern's rank for the Post component is equal to that of the TagPost route path and will mask it. You'll need to differentiate/disambiguate the sub-routes, for example placing the TagPost component an another sub-route like "/blog/tag/:tagVal".
Example:
<Route path="/blog" element={<Blog />} >
<Route index element={<Allblogs />} />
<Route path=":id" element={<Post />} />
<Route path='/tag/:tagVal' element={<TagPost />} />
</Route>
I am designing a users dashboard in React, wherein User logs in and navigate to his dashboard with other links such as Archived, Profile and Settings. My Login and then Navigating to HomePage is working fine.
I have designed the Dashboard, Archived, Profile and Settings Page Links in Sidebar. Now when I am navigating to the Links. It takes me to a new URL path and my Sidebar disappears. I want my sidebar to still appear on all pages as long as I am logged in.
Below is my App.js where I have designed the upper level route:
return (
<div>
<Router history={history}>
<Switch>
<PrivateRoute exact path="/" component={HomePage} />
<Route path="/login" component={LoginPage} />
<Route path="/register" component={RegisterPage} />
<Redirect from="*" to="/" />
</Switch>
</Router>
</div>
);
Once User is on HomePage, I need the dashboard and other links to show. and when User clicks on any Sidebar link, Sidebar should still be there while the other page opens. So I added the inner Routes to the HomePage.jsx like this:
return (
<div>
<Router history={history}>
<Sidebar />
<Switch>
<Route path="/" component={Dashboard} />
<Route path="/archived" component={ArchivedPage} />
<Route path="/profile" component={ProfilePage} />
<Route path="/settings" component={SettingsPage} />
{/* <Redirect from="*" to="/" /> */}
</Switch>
</Router>
</div>
);
But it doesn't work. Can anyone please help me understanding if this is correct. or how can I achieve the required result.
Please let me know if you need any other details.
Thank you.
Issue
The issue is that you are exactly matching "/" to render HomePage, but then as soon as the path is any deeper, like "/archived", it no longer exactly matches and HomePage is unmounted.
You should not render a Router within another Router, you need only one router per app to provide the routing context.
Solution
Remove the inner router (and any other nested routers!!). Remove the exact prop on the "/" path and reorder the routes to specify the more specific paths before less specific paths so the Switch can actually do its job and match and render the appropriate route.
App
Reorder the more specific "/login" and "/register" paths to be matched prior to the less specific "/" path. If you had, for example, a "/login/google" path, this is more specific than "/login" and would be ordered earlier.
return (
<div>
<Router history={history}>
<Switch>
<Route path="/login" component={LoginPage} />
<Route path="/register" component={RegisterPage} />
<PrivateRoute path="/" component={HomePage} />
<Redirect to="/" />
</Switch>
</Router>
</div>
);
HomePage
Move the Dashboard to the last route position so if no other route above it is matched and returned then the dashboard is matched and rendered.
return (
<div>
<Sidebar />
<Switch>
<Route path="/archived" component={ArchivedPage} />
<Route path="/profile" component={ProfilePage} />
<Route path="/settings" component={SettingsPage} />
<Route component={Dashboard} />
</Switch>
</div>
);
in first place your doing something wrong you cant put a Router inside a Router,
you haver a Router in app then inside a component that is inside of app you have another Router thats a problem i dont know if that solves your problem but try it just delete Router in homepage
I have React Router setup in my Reactjs Project. The header Component has 4 different menu items. After login, I am getting only header component rendered but not first menu item component below it.
I have created a Homepage component which loads Header component and below that I gave Routes for different menu item pages. In the Header component for every Item, I linked it to the corresponding Item Page.
//Home Page Code.
<Router>
<Header />
<Route path='/Jobs' component={Jobs} />
<Route path='/Admin' component={Admin} />
<Route path='/Requests' component={Requests} />
</Router>
To use react router you have to wrap your routes in switch.
Switch will render the first item that matches the current route.
Because you have no switch, the routes are ignored.
To render a default site, change the path of the last route to / and it will match everything.
By setting it as last element, it will always be rendered, if no other route above matches the current route.
<Router>
<Header />
<Switch>
<Route path='/Jobs' component={Jobs} />
<Route path='/Admin' component={Admin} />
<Route path='/' component={Requests} />
</Switch>
</Router>
Hope this helps. Happy coding.
Try putting <Switch></Switch> container around your routes:
//Home Page Code.
<Router>
<Header />
<Switch>
<Route exact path='/' component={Home} />
<Route path='/Jobs' component={Jobs} />
<Route path='/Admin' component={Admin} />
<Route path='/Requests' component={Requests} />
</Switch>
</Router>
Edited: to add path for home (path='/')
When I try to have nested routes on my root route I run into a problem.
I have 3 "main" routes:
<Switch>
<Route path="/" component={Home} />
<Route path="/login" component={Login} />
<Route path="/logout" component={Logout} />
</Switch>
On my Home component I have a nested router like this:
<div>
<Route path="/" render={() => <div>Home</div>} />
<Route path="/test" render={() => <div>Test Route</div>} />
</div>
The Home component has a sidebar HOC which contains the Links.
<Sidebar>
<Link to="/">Home</Link>
<Link to="/test">Test</Link>
<Link to="/logout">Logout</Link>
</Sidebar>
When Im on my Root component and click the Test link, the route on the nested router changes to the Test component which is correct. Whenever I go the login and/or logout route it tries to display that in the nested router in the Home component
Any idea what is going wrong?
EDIT: I've tried the example #Tholle provided. Unfortunately it still doesn't work the way I want to. See this CodeSandBox I made to reproduce my problem.
your links need to point to "/home/testX" and the nested routes need to handle "/home/testX". Also you will need a route for "/home" in the root. I don't believe the Link component is scoped to the route in which it is called. Meaning that to link to "/test1" assumes that is the base route. However, the rendering of test1 actually takes place in the home component.
To put it another way: In order to get to /home/test1 you must first get the home component (/home) to render which can then render the route for test1 (/home/test1)
Here's the codesandbox
Here is an example that provides a bit more flexibility codesandbox. This one will require a redirect of "/" because it depends on the path being used and it needs to be "/home" not "/".
Hope this helps. Hope I got it all right.
The Switch component makes sure that only the first Route that matches is rendered. To stop <Route path="/" component={Home} /> from always being rendered, you can set the exact prop to true.
Example (CodeSandbox)
<Switch>
<Route exact path="/" component={Home} />
<Route path="/login" component={Login} />
<Route path="/logout" component={Logout} />
</Switch>
I have an applications index page that lists all my applications. The index page is also the default route. I want to nest a 'applications new' modal in the index page. This way I can render the modal while on top of the index page. However, I'm not able to nest within the default route successfully.
Here's how I think it should work
<Route name='applications' path='/applications' handler={Applications}>
<DefaultRoute name="index" handler={ApplicationIndex}>
<Route name='applicationNew' path='/new' handler={ApplicationNewModal}/>
</DefaultRoute>
<Route name="applicationShow" path=':key' handler={ApplicationShow}/>
</Route>
When I try to transition to 'applicationNew' I get an error saying that no route was found with that name
You need to move it to its own Route inside a Route with handler={ApplicationIndex}.
<Route name='applications' path='/applications' handler={Applications}>
<DefaultRoute name="index" handler={ApplicationIndex} />
<Route handler={ApplicationIndex}>
<Route name='applicationNew' path='/new' handler={ApplicationNewModal} />
</Route>
<Route name="applicationShow" path=':key' handler={ApplicationShow}/>
</Route>