React Router nested routes - javascript

I have routes:
<Switch>
<Route path="/about" component={About} />
<Route path="/about/Us" component={AboutUs} />
<Route path="/about/Company" component={AboutCompany} />
</Switch>
I would like the /about route to show about component and its children (AboutUs and AboutCompany) but the /about route is only rendering About component. How can I fix that? I have react-router 4

There are 2 ways you can achieve it.
Creating nested routes from routes.js/jsx
Creating nested routes from the parent component (about.js/jsx)
If it is from routes.js/jsx
<Switch>
<Route path="/about" component={About}>
<Route path="/about/Us" component={AboutUs} />
<Route path="/about/Company" component={AboutCompany} />
</Route>
</Switch>
If it is from routes.js/jsx
//Routes.jsx/js
<Switch>
<Route path="/about" component={About} />
</Switch>
and
//About.jsx/js
<Switch>
<Route path="/about/Us" component={AboutUs} />
<Route path="/about/Company" component={AboutCompany} />
</Switch>

<Switch>
<Route exact path="/about" component={About} />
<Route path="/about/Us" component={AboutUs} />
<Route path="/about/Company" component={AboutCompany} />
</Switch>
You need to add the exact keyword to About parent path.

Related

How to load multiple routes in index file using react

I have a following index file -
<BrowserRouter>
<Routes>
<Route path="/" element={Home}
<Route element={Navigation}
</Routes>
</BrowserRouter>
I have multiple routes which I have to load So For that I have written a component:
const Navigation = () => {
<>
<Route path="/not-available-primary" element={NotAvaliable}/>
<Route path="/not-available-Secondary" element={Avaliable}/>
<Route path="/available-primary" element={Primary}/>
<Route path="/available-Secondary" element={Secondary}/>
<Route path="/direct-debit-primary" element={DirectDBB}/>
<Route path="/direct-debit-secondary" element={DirectDBBSecondary}/>
</>
}
But here, it does not render the component and gives no routes matched for location.
How do I fix this ?
You have to give a Component to the element prop, like this:
<BrowserRouter>
<Routes>
<Route path="/" element={<Home />} />
<Route path="/*" element={<Navigation />} />
</Routes>
</BrowserRouter>
and
const Navigation = () => {
return (<>
<Route path="/not-available-primary" element={<NotAvaliable />}/>
<Route path="/not-available-Secondary" element={<Avaliable />}/>
<Route path="/available-primary" element={<Primary />}/>
<Route path="/available-Secondary" element={<Secondary />}/>
<Route path="/direct-debit-primary" element={<DirectDBB />}/>
<Route path="/direct-debit-secondary" element={<DirectDBBSecondary />}/>
</>)
}
or
<BrowserRouter>
<Routes>
<Route path="/" element={<Home />} />
<Route path="/*">
<Route path="not-available-primary" element={<NotAvaliable />}/>
<Route path="not-available-Secondary" element={<Avaliable />}/>
<Route path="available-primary" element={<Primary />}/>
<Route path="available-Secondary" element={<Secondary />}/>
<Route path="direct-debit-primary" element={<DirectDBB />}/>
<Route path="direct-debit-secondary" element={<DirectDBBSecondary
/>}/>
</Route>
</Routes>
</BrowserRouter>
Note that in the seconds solution (nested routes) I erased the "/".
Documentation here
in your index file
<Route path="/" compoment={Home}
if "Navigation" is your class
const Navigation = () => {
return (
<>
<Routes>
<Route path="/not-available-primary" component={NotAvaliable}/>
<Route path="/not-available-Secondary" component={Avaliable}/>
<Route path="/available-primary" component={Primary}/>
<Route path="/available-Secondary" component={Secondary}/>
<Route path="/direct-debit-primary" component={DirectDBB}/>
<Route path="/direct-debit-secondary" component={DirectDBBSecondary}/>
</Routes>
</>
)
}
Issue
It's unclear which version of react-router-dom you are trying to use. version 4/5 or 6, but you've syntax issues for either. The route rendering the Navigation component needs a path with a trailing "*" character to be matched at the root/base level so the descendent routes can then also be matched and rendered.
Using react-router-dom#5
Use the Switch component instead of the Routes component. The Route components use the component (or render or children function props). The home path "/" must exactly match in order for any other route to be matched when the path isn't exactly "/", e.g. "/not-available-primary".
<BrowserRouter>
<Switch>
<Route path="/" exact component={Home} />
<Route path="*" component={Navigation} />
</Switch>
</BrowserRouter>
...
const Navigation = () => {
<Switch>
<Route path="/not-available-primary" component={NotAvaliable} />
<Route path="/not-available-Secondary" component={Avaliable} />
<Route path="/available-primary" component={Primary} />
<Route path="/available-Secondary" component={Secondary} />
<Route path="/direct-debit-primary" component={DirectDBB} />
<Route path="/direct-debit-secondary" component={DirectDBBSecondary} />
</Switch>
};
Using react-router-dom#6
All Route components can only be rendered by a Routes component or another Route component in the case of route nesting. The Route component API changed significantly and there is now only a single element prop taking a ReactNode, a.k.a. JSX, as a value. In RRDv6 all routes are now always exactly matched and use a route ranking system; there is no longer an exact prop for Route components.
<BrowserRouter>
<Routes>
<Route path="/" element={<Home />} />
<Route path="*" element={<Navigation />} />
</Routes>
</BrowserRouter>
...
const Navigation = () => {
<Routes>
<Route path="/not-available-primary" element={<NotAvaliable />} />
<Route path="/not-available-Secondary" element={<Avaliable />} />
<Route path="/available-primary" element={<Primary />} />
<Route path="/available-Secondary" element={<Secondary />} />
<Route path="/direct-debit-primary" element={<DirectDBB />} />
<Route path="/direct-debit-secondary" element={<DirectDBBSecondary />} />
</Routes>
};
At the first use <Switch> in Navigation component :
const Navigation = () => {
<Switch>
<Route path="/not-available-primary" component={NotAvaliable}/>
<Route path="/not-available-Secondary" component={Avaliable}/>
<Route path="/available-primary" component={Primary}/>
<Route path="/available-Secondary" component={Secondary}/>
<Route path="/direct-debit-primary" component={DirectDBB}/>
<Route path="/direct-debit-secondary" component={DirectDBBSecondary}/>
</Switch>
}
so, add the component to Route:
<BrowserRouter>
<Switch>
<Route path="/" exact component={Home} />
<Route path="/login" exact component={LoginForm} />
<Route component={Navigation} />
</Switch>
</BrowserRouter>

React how can i redirect the homepage?

My problem is ı have a routes like that but when i try for example http://localhost:3000/examp1
I just want to redirect to HomePage how can i do that when i write something http://localhost:3000/*** ı go the page but nothing shows how can i detect and how can i redirect the homepage ? anyone help ?
<Router>
<Switch>
<Route path='/' component={Home} exact />
<Route path='/xyz' component={asf} exact />
<Route path='/asd' component={asd} exact />
<Route path='/fasd/:slug' component={asd} exact />
<Route path='/asd' component={asd} exact />
<Route path='/asd/:slug' component={asd} exact />
<Route path='/asd' component={asd} exact />
<Route path='/asd' component={fas} exact />
<Route path='/asd' component={fasd} exact />
</Switch>
</Router>
Adding a <Route /> at the bottom without a path attribute inside the <Switch> tag should work for when there's no match, and then use a <Redirect /> tag to redirect to the homepage.
<Router>
<Switch>
<Route path='/' component={Home} exact />
<Route path='/xyz' component={asf} exact />
<Route path='/asd' component={asd} exact />
<Route path='/fasd/:slug' component={asd} exact />
<Route path='/asd' component={asd} exact />
<Route path='/asd/:slug' component={asd} exact />
<Route path='/asd' component={asd} exact />
<Route path='/asd' component={fas} exact />
<Route path='/asd' component={fasd} exact />
<Route component={() => <Redirect to="/" />} />
</Switch>
</Router>
How to properly render a 404 page in React with React-Router?
https://reactrouter.com/web/api/Redirect
You can simply use Redirect component of react-router-dom library.
<Router>
<Switch>
<Route path='/' component={Home} exact />
<Route path='/xyz' component={asf} exact />
<Route path='/asd' component={asd} exact />
<Route path='/fasd/:slug' component={asd} />
<Route path='/asd' component={asd} exact />
<Route path='/asd/:slug' component={asd} />
<Redirect to="/" />
</Switch>
</Router>
DefaultRoute and NotFoundRoute were removed in react-router 1.0.0.
I'd like to emphasize that the default route with the asterisk has to be last in the current hierarchy level to work. Otherwise it will override all other routes that appear after it in the tree because it's first and matches every path.
For react-router 1, 2 and 3
If you want to display a 404 and keep the path (Same functionality as NotFoundRoute)
<Route path='*' exact={true} component={My404Component} />
If you want to display a 404 page but change the url (Same functionality as DefaultRoute)
<Route path='/404' component={My404Component} />
<Redirect from='*' to='/404' />
Example with multiple levels:
<Route path='/' component={Layout} />
<IndexRoute component={MyComponent} />
<Route path='/users' component={MyComponent}>
<Route path='user/:id' component={MyComponent} />
<Route path='*' component={UsersNotFound} />
</Route>
<Route path='/settings' component={MyComponent} />
<Route path='*' exact={true} component={GenericNotFound} />
</Route>
For react-router 4 and 5
Keep the path
<Switch>
<Route exact path="/users" component={MyComponent} />
<Route component={GenericNotFound} />
</Switch>
Redirect to another route (change url)
<Switch>
<Route path="/users" component={MyComponent} />
<Route path="/404" component={GenericNotFound} />
<Redirect to="/404" />
</Switch>
The order matters!
I ma using Navigate to redirect from "/" to "/home"
import {BrowserRouter, Navigate, Route, Routes,} from "react-router-dom";
<BrowserRouter>
<Routes>
<Route exact path="/" element={<Navigate to="/home"/>} />
</Routes>
</BrowserRouter>

How to put a div inside a Switch with React Router?

I have an APP using React and Redux, and I wanted to load a NotFound component when the user enters an invalid route. I found online a way to solve that problem, that is by putting all the routes inside a switch, including the NotFound component.
The problem is that, in my app, I can't put all my routes inside a Switch because There is a single component that needs to be stretched to the entire page, while all the other components need to be inside a "container". The way I have it below (see the code), the NotFound component works for all cases, except when I'm on the "landing" component route (where the NotFound component always displays).
I tried to put the landing component inside the Switch with the "container" div but the app crashes.
Is there any way to solve this? (keeping the landing component out of the container, and the other components inside)
class App extends Component {
render() {
return (
<Provider store={store}>
<Router>
<div className="App">
<Navbar />
<Route exact path="/" component={Landing} />
<div className="container">
<Switch>
<Route exact path="/register" component={Register} />
<Route exact path="/login" component={Login} />
<Route exact path="/profiles" component={Profiles} />
<Route exact path="/profile/:handle" component={Profile} />
<PrivateRoute exact path="/dashboard" component={Dashboard} />
<PrivateRoute
exact
path="/create-profile"
component={CreateProfile}
/>
<PrivateRoute
exact
path="/edit-profile"
component={EditProfile}
/>
<PrivateRoute
exact
path="/add-experience"
component={AddExperience}
/>
<PrivateRoute
exact
path="/add-education"
component={AddEducation}
/>
<PrivateRoute
exact
path="/edit-education/:id"
component={EditEducation}
/>
<PrivateRoute exact path="/feed" component={Posts} />
<PrivateRoute exact path="/post/:id" component={Post} />
<Route component={NotFound}/>
</Switch>
</div>
<Footer />
</div>
</Router>
</Provider>
);
}
}
You can make a separate router for all other components except landing page.
// App.js
import NonLandingPages from './NonLandingPages';
class App extends Component {
render() {
return (
<Provider store={store}>
<Router>
<div className="App">
<Navbar />
<Switch>
<Route exact path="/" component={Landing} />
<Route component={NonLandingPages}/>
</Switch>
<Footer />
</div>
</Router>
</Provider>
);
}
}
Separate router for all other pages
// NonLandingPages.js
class NonLandingPages extends Component {
render() {
return (
<div className="container">
<Switch>
<Route exact path="/register" component={Register} />
<Route exact path="/login" component={Login} />
<Route exact path="/profiles" component={Profiles} />
<Route exact path="/profile/:handle" component={Profile} />
<PrivateRoute exact path="/dashboard" component={Dashboard} />
<PrivateRoute
exact
path="/create-profile"
component={CreateProfile}
/>
<PrivateRoute
exact
path="/edit-profile"
component={EditProfile}
/>
<PrivateRoute
exact
path="/add-experience"
component={AddExperience}
/>
<PrivateRoute
exact
path="/add-education"
component={AddEducation}
/>
<PrivateRoute
exact
path="/edit-education/:id"
component={EditEducation}
/>
<PrivateRoute exact path="/feed" component={Posts} />
<PrivateRoute exact path="/post/:id" component={Post} />
<Route component={NotFound}/>
</Switch>
</div>
);
}
}

Route is not matched

I can't figure out why this is not matching my route for the CompanyDetailContainer. The route for Interview container works fine
<IndexRoute component={HomePageContainer} />
<Route component={InterviewContainer} name="interview" path="interviews/companies/:companyId" />
<Route component={CompanyDetailContainer} name="companydetail" path="interviews/companies/:companyId/details" />
so http://localhost:8080/interviews/companies/10 hits the interview route fine but http://localhost:8080/interviews/companies/501/details does not hit the companydetail route
UPDATE:
I'm using:
"react-router": "^3.0.0",
"react-router-dom": "^4.2.2",
original code:
import { IndexRoute, Router, Route, browserHistory } from 'react-router';
<Router history={browserHistory} onUpdate={onUpdate}>
<Route path="/">
<IndexRoute component={HomePageContainer} />
<Switch>
<Route exact component={InterviewContainer} name="interview" path="interviews/companies/:companyId" />
<Route exact component={CompanyDetailContainer} name="companydetail" path="interviews/companies/:companyId/details" />
</Switch>
<Route component={About} name="about" path="about" />
<Route component={JobList} name="jobs" path="jobs" />
</Route>
<Route component={Container} path="/" />
<Route component={NotFound} path="*" />
</Router>
adding just exact to what I had didn't work:
import { IndexRoute, Router, Route, browserHistory } from 'react-router';
<Router history={browserHistory} onUpdate={onUpdate}>
<Route path="/" component={HomePageContainer}>
<Route component={InterviewContainer} exact name="interview" path="interviews/companies/:companyId" />
<Route component={CompanyDetailContainer} exact name="companydetail" path="interviews/companies/:companyId/details" />
<Route component={About} name="about" path="about" />
<Route component={JobList} name="jobs" path="jobs" />
<Route component={Container} path="/" />
<Route component={NotFound} path="*" />
</Route>
</Router>
Then I tried to add switch around it:
import { Router, Route, Switch, browserHistory } from 'react-router';
<Router history={browserHistory} onUpdate={onUpdate}>
<Switch>
<Route path="/" component={HomePageContainer}>
<Route component={InterviewContainer} exact name="interview" path="interviews/companies/:companyId" />
<Route component={CompanyDetailContainer} exact name="companydetail" path="interviews/companies/:companyId/details" />
<Route component={About} name="about" path="about" />
<Route component={JobList} name="jobs" path="jobs" />
<Route component={Container} path="/" />
<Route component={NotFound} path="*" />
</Route>
</Switch>
</Router>
And now I get this error: Cannot read property 'createRouteFromReactElement' of undefined. I noticed my import for Switch is not resolving but that's how you import Switch right?
Also not sure if all those routes should be sub routes of <Route path="/" component={HomePageContainer}>? Note that I removed the <IndexRoute /> per suggestions too.
React Router V4 is split out into two packages. One for Web (DOM) and one for Native.
Therefore, you don’t need the react-router dependency, just react-router-dom.
So import the components from react-router-dom instead:
import { BrowserRouter, Route, Switch } from 'react-router-dom'
You can then wrap your routes in a Switch so that only one route is matched.
If you put your details route above the other then it should match first:
<BrowserRouter>
<Switch>
<Route exact path="/" component={HomePageContainer} />
<Route path="/interviews/companies/:companyId/details" component={CompanyDetailContainer} />
<Route path="/interviews/companies/:companyId" component={InterviewContainer} />
<Route path="/about" component={About} />
<Route path="/jobs" component={JobList} />
<Route component={NotFound} />
</Switch>
</BrowserRouter>
Also note that with React Router V4, you don’t nest routes. Instead you can add additional routes within your components.
Reverse the two routes with a wrapping with Switch :
import {Switch} from 'react-router';
<IndexRoute component={HomePageContainer} />
<Switch>
<Route component={CompanyDetailContainer} name="companydetail" path="interviews/companies/:companyId/details" />
<Route component={InterviewContainer} name="interview" path="interviews/companies/:companyId" />
</Switch>
There are 2 possible solutions:
Use a Switch, which is used to exclusively render just one route.
Use the exact prop of the Route component, which renders the component only if the path is an exact match.
Eg:
<Switch>
<Route exact component={InterviewContainer} name="interview" path="interviews/companies/:companyId" />
<Route exact component={CompanyDetailContainer} name="companydetail" path="interviews/companies/:companyId/details" />
</Switch>
P.S. I think you wouldn't need IndexedRoute when using Switch ( but you better check it in the docs of the version you are using)

Index routes with nested routes in React-router v3

I am planning to have the following route setup in my app. I am currently using React-Router 2.7.
/
/stored_systems
/stored_systems/schemas/:schema_id
/stored_systems/schemas/:schema_id/systems/:system_id
/runtime
/runtime/mainlines/:mainline_id
/runtime/mainlines/:mainline_id/valve_groups/:valve_group_id
I have written the router configuration as follows.
<Route path='/' component={App}>
<IndexRoute component={StoredSystems} />
<Route path='/stored_systems' component={StoredSystems} >
<IndexRoute component={SchemasList} />
<Route path='/stored_systems/schemas/:schema_id' component={Schema} />
<Route path='/stored_systems/schemas/:schema_id/systems/:system_id' component={System} />
</Route>
<Route path='/runtime' component={Runtime} >
<IndexRoute component={MainLinesList} />
<Route path='/runtime/mainlines/:mainline_id' component={Mainline} />
<Route path='/runtime/mainlines/:mainline_id/valve_groups/:valve_group_id' component={ValveGroup} />
</Route>
</Route>
The StoredSystems and Runtime are stateless components which basically render {props.children}.
Now, if I go to /stored_systems, it will properly render the SchemasList component. Routes like /stored_systems/schemas/schema1 would render properly.
However, if I go to /, it will render the StoredSystems component, without its children. Well, there aren't really any children defined, because it is loading an IndexRoute.
How do I render the SchemaList inside StoredSystems when I navigate to the root?
Move the / in your path and setup routes like
<Route component={App}>
<Route path = '/' component={StoredSystems} >
<IndexRoute component={SchemasList} />
</Route>
<Route path='/stored_systems' component={StoredSystems} >
<IndexRoute component={SchemasList} />
<Route path='/stored_systems/schemas/:schema_id' component={Schema} />
<Route path='/stored_systems/schemas/:schema_id/systems/:system_id' component={System} />
</Route>
<Route path='/runtime' component={Runtime} >
<IndexRoute component={MainLinesList} />
<Route path='/runtime/mainlines/:mainline_id' component={Mainline} />
<Route path='/runtime/mainlines/:mainline_id/valve_groups/:valve_group_id' component={ValveGroup} />
</Route>
</Route>

Categories