P.S. Also make sure that you are passing {...props} so that the default router props like location, history, match etc are also getting passed on to the Home component otherwise the only prop that is getting passed down to it is test. 1 you should add the props parameter to the function you pass in and use it in the component 'Home' with {...props} otherwise you would lose the standard props react router v4 passes in – pczern Aug 27, 2017 at 20:59 1 @speedDeveloper, I don't think its a quick fix, and the router props will be passed if you pass it to the component in render(). I missed that part in the answer. However I updated it to include the same – Shubham Khatri Aug 28, 2017 at 5:25
//This only applies for earler versions of React Router specifically v5
<Route
path='/dashboard'
render={(props) => (
<Dashboard {...props} isAuthed={true} />
)}
/>
So you can pass the prop to component like
<Route path="/" exact render={(props) => (<Home test="hi" {...props}/>)} />
and then you can access it like
this.props.test
However, with React Router v6, since you're in charge of creating the element, you just pass a prop to the component as you normally would. In previous versions of React Router (v4), this was non-trivial since React Router was in charge of creating the React element. To get around this, you'd have to use Routes render prop. Bytes is the developer newsletter I most look forward to each week. Great balance of content and context! Thanks @uidotdev. Now, what if we also wanted to pass the Dashboard component a prop?
<Route path="/dashboard" element={<Dashboard />} />
// React Router v4<Route path="/dashboard" render={(props) => <Dashboard {...props} authed={true} />}/>
<Route path="/dashboard" element={<Dashboard authed={true} />} />
To recap, if you need to pass data from Link through to the new component that's being rendered, pass Links a state prop with the data you want to pass through. There are a few different approaches, but the one we'll focus on in this post is centered around being able to pass data from one route to another. To do this with React Router, we can pass data from the Link component through to the new Route that is being rendered. Anytime you pass data along via the state property, that data will be available on the location's state property, which you can get access to by using the custom useLocation Hook that comes with React Router.
<Link to={`/onboarding/profile`}>Next Step</Link>
<Link to="/onboarding/profile" state={{ from: "occupation" }}> Next Step</Link>
import {
useLocation
} from 'react-router-dom'
function Profile() {
const location = useLocation() const {
from
} = location.state
return (...)
}
Internally, react router use React.createElement to render the component passed to the component props. If we pass a function to it, it will create a new component on every render instead of just updating the existing component. We have seen several examples and use cases in react router. One among them is passing props to the route component directly. React router provides an easy solution for this case. Instead of passing function through component props, we can pass it through render props. While passing our own props, we also need to pass the default props send to the render props by react router. Lets see it in our example,
// App.js
...
const PropsPage = () => { return ( <h3>Props Page</h3> );};
const App = () => {
return (
<section className="App">
<Router>
...
<Link to="/404-not-found">404</Link>
<Link to="/props">Passing Props</Link> <Switch>
...
<Route exact path="/props" component={PropsPage} /> <Route component={NoMatchPage} />
</Switch>
</Router>
<a href="/about">about with browser reload</a>
</section>
);
};
export default App;
...
const PropsPage = ({ title }) => {
return (
<h3>{title}</h3>
);
};
...
<Route exact path="/props-through-component" component={() => <PropsPage title={`Props through component`} />} />
...
<Link to="/props-through-render">Props through render</Link>
...
<Route exact path="/props-through-render" render={(props) => <PropsPage {...props} title={`Props through render`} />} />
As previously mentioned, React Router v6 allows routes to accept components as elements when constructing routes, and pass custom props to components. We may also nest routes and use relative links as well. This helps us prevent or reduce the definition of new routes inside various component files and makes it easy to pass global data to components and props. We had three different techniques for generating routes in React Router v5, which caused confusion. The first technique is to pass the component and path as props of the Route component: In v6, Routes can contain only Route or React.Fragment children, so make sure to move other HTML elements and components to suitable places from the Routes component.
Look at the following example that demonstrates the ranking problem in the v5’s routing algorithm:
The correct way: Here, /games
will render the Games
component but not SelectedGame
, because it does not have a parameter id
. While /games/:id
will render only the SelectedGame
component:
<Router>
<Route path="/games/:id" component={SelectedGame} />
<Route path="/games" component={Games} />
</Router>
The incorrect way: Here, either /games
or /games/:id
will render the Games
component:
<Router>
<Route path="/games" component={Games} />
<Route path="/games/:id" component={SelectedGame} />
</Router>
According to v5’s perspective, the second approach is incorrect, and developers need to use the exact
prop or re-order (as in the first code snippet) to fix it. But, the v5 route ranking algorithm could be intelligent to identify the most suitable route without explicit ordering or exact
usage.
For developing nested routes, developers had to use write more code with the useRouteMatch
Hook, Route
, and Switch
components. For nested routes, developers had to find the entire route because there is no relative route handling in v5:
// ----
<Switch>
<Route path="/dashboard" component={Dashboard} />
</Switch>;
// ----
function Dashboard() {
const { path } = useRouteMatch();
return (
<div>
<h1>Dashboard</h1>
<Switch>
<Route path={`${path}/charts`} component={Charts} />
</Switch>
</div>
);
}
Next, run the following command to initiate an upgrade:
npm install[email protected]
#-- - or-- -
yarn install[email protected]
First, open a terminal in a project directory where React Router isn’t installed. To install a specific version of React Router, run the following:
npm install[email protected][VERSION_TO_BE_INSTALLED]
The readability of co-located, nested <Route>s that we had in v3 but also with support for code splitting and passing custom props through to your route components Hooks eliminate both the need to use <Route render> to access the router's internal state (the match) and the need to pass props around manually to propagate that state to child components. Now contrast this simple example with how you might have done the same thing in v5 or prior with a render prop or a higher-order component.
import { Routes, Route, useParams } from "react-router-dom";
function App() {
return (
<Routes>
<Route path="blog/:id" element={<BlogPost />} />
</Routes>
);
}
function BlogPost() {
// You can access the params here...
let { id } = useParams();
return (
<>
<PostHeader />
{/* ... */}
</>
);
}
function PostHeader() {
// or here. Just call the hook wherever you need it.
let { id } = useParams();
}
// React Router v5 code
import * as React from "react";
import { Switch, Route } from "react-router-dom";
class App extends React.Component {
render() {
return (
<Switch>
<Route
path="blog/:id"
render={({ match }) => (
// Manually forward the prop to the <BlogPost>...
<BlogPost id={match.params.id} />
)}
/>
</Switch>
);
}
}
class BlogPost extends React.Component {
render() {
return (
<>
{/* ...and manually pass props down to children... booo */}
<PostHeader id={this.props.id} />
</>
);
}
}
import {
useEffect
} from "react";
import {
useLocation
} from "react-router-dom";
function App() {
let location = useLocation();
useEffect(() => {
window.ga("set", "page", location.pathname + location.search);
window.ga("send", "pageview");
}, [location]);
}
// React Router v5 code
import * as React from "react";
import { Switch, Route } from "react-router-dom";
class PageviewTracker extends React.Component {
trackPageview() {
let { location } = this.props;
window.ga("set", "page", location.pathname + location.search);
window.ga("send", "pageview");
}
componentDidMount() {
this.trackPageview();
}
componentDidUpdate(prevProps) {
if (prevProps.location !== this.props.location) {
this.trackPageview();
}
}
render() {
return null; // lol
}
}
class App extends React.Component {
return (
<>
{/* This route isn't really a piece of the UI, it's just here
so we can access the current location... */}
<Route path="/" component={PageviewTracker} />
<Switch>
{/* your actual routes... */}
</Switch>
</>
);
}
import { render } from "react-dom";
import { BrowserRouter } from "react-router-dom";
// import your route components too
render(
<BrowserRouter>
<Routes>
<Route path="/" element={<App />}>
<Route index element={<Home />} />
<Route path="teams" element={<Teams />}>
<Route path=":teamId" element={<Team />} />
<Route path="new" element={<NewTeamForm />} />
<Route index element={<LeagueStandings />} />
</Route>
</Route>
</Routes>
</BrowserRouter>,
document.getElementById("root")
);