React Router v6 is being gradually improved and will be released in the near future.
Let’s find out through the positive changes of this v6 version compared to the previous version (v5) okay (go)
1. <Switch>
is becoming <Routes>
Component
top-level Component
changed its name from <Switch>
to <Routes>
, but mostly its old functionality remained the same.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | // v5 import { BrowserRouter, Switch, Route } from 'react-router-dom'; function App() { return ( <BrowserRouter> <Switch> <Route exact path="/"><Home /></Route> <Route path="/profile"><Profile /></Route> </Switch> </BrowserRouter> ); } |
With React Router v6, we just need to change it with <Routes>
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | // v6 import { BrowserRouter, Routes, Route } from 'react-router-dom'; function App() { return ( <BrowserRouter> <Routes> <Route path="/" element={<Home />} /> <Route path="profile/*" element={<Profile />} /> </Routes> </BrowserRouter> ); } |
2 Big Changes with <Route>
In v6 <Route>
seems to receive the most changes, new changes make the use and understanding become much simpler.
The props component
or render
in v5 will be changed to element
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | import Profile from './Profile'; // v5 <Route path=":userId" component={Profile} /> <Route path=":userId" render={routeProps => ( <Profile routeProps={routeProps} animate={true} /> )} /> // v6 <Route path=":userId" element={<Profile />} /> <Route path=":userId" element={<Profile animate={true} />} /> |
Note:
- Also
<Route exact />
has been omitted, because all<Route>
paths are by defaultexact
. If you want to create a path for multiple<Route>
with many customizations, you can use the*
sign similar to the example above<Route path="profile/*" element={<Profile />} />
- Note
<Route path>
patterns
React Router v6 uses a simple format that only supports one type of dynamic URL :id
and *
, with *
only at the end of the url, not in the middle
Valid route formats in v6:
1 2 3 4 5 6 7 8 | /groups /groups/admin /users/:id /users/:id/messages /files/* /files/:id/* /files-* |
Routes written in RegExp
structure will not be valid in v6:
1 2 3 4 | /users/:id? /tweets/:id(d+) /files/*/cat.jpg |
The removal of the structure written in RegExp
help decrease the file size and makes syntax bundle of Route
simpler, more readable
3. Nested Routes are Simpler
Nested routes in v5 require you to specify the url to be able to render the component correctly, requiring the use of string-matching logic (for example, combining strings), for example:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 | // v5 import { BrowserRouter, Switch, Route, Link, useRouteMatch } from 'react-router-dom'; function App() { return ( <BrowserRouter> <Switch> <Route exact path="/" component={Home} /> <Route path="/profile" component={Profile} /> </Switch> </BrowserRouter> ); } function Profile() { let match = useRouteMatch(); return ( <div> <nav> <Link to={`${match.url}/me`}>My Profile</Link> </nav> <Switch> <Route path={`${match.path}/me`}> <MyProfile /> </Route> <Route path={`${match.path}/:id`}> <OthersProfile /> </Route> </Switch> </div> ); } |
With React Router v6, you can skip the string-matching logic ( match.path
as above), nor do you need to use useRouteMatch()
hook. Your code will be much easier to read:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 | // v6 import { BrowserRouter, Routes, Route, Link, Outlet } from 'react-router-dom'; // Approach #1 function App() { return ( <BrowserRouter> <Routes> <Route path="/" element={<Home />} /> <Route path="profile/*" element={<Profile/>} /> </Routes> </BrowserRouter> ); } function Profile() { return ( <div> <nav> <Link to="me">My Profile</Link> </nav> <Routes> <Route path="me" element={<MyProfile />} /> <Route path=":id" element={<OthersProfile />} /> </Routes> </div> ); } // Ngoài ra, bạn cũng có thể định nghĩa tất cả routes trong một file, sau đó sử dụng `<Outlet>` function App() { return ( <BrowserRouter> <Routes> <Route path="/" element={<Home />} /> <Route path="profile" element={<Profile />}> <Route path=":id" element={<MyProfile />} /> <Route path="me" element={<OthersProfile />} /> </Route> </Routes> </BrowserRouter> ); } function Profile() { return ( <div> <nav> <Link to="me">My Profile</Link> </nav> <Outlet /> </div> ) } |
Note: the <Outlet> component is used like {this.props.children} in React Router v6. This was a very popular feature from Reach Router!
- Note: The
<Outlet> component
is used similarly to{this.props.children}
in React Router v6.
4. useNavigate
Instead of useHistory
With previous versions we often used history
in hook useHistory
to navigate. But in this React Router v6, useHistory
has been renamed to useNavigate
1 2 3 4 5 6 7 8 9 10 11 | // v5 import { useHistory } from 'react-router-dom'; function MyButton() { let history = useHistory(); function handleClick() { history.push('/home'); }; return <button onClick={handleClick}>Submit</button>; }; |
history.push()
will be replaced with navigate()
:
1 2 3 4 5 6 7 8 9 10 11 | // v6 import { useNavigate } from 'react-router-dom'; function MyButton() { let navigate = useNavigate(); function handleClick() { navigate('/home'); }; return <button onClick={handleClick}>Submit</button>; }; |
In some cases, we want to change the URL, not push the new URL:
1 2 3 4 5 | // v5 history.push('/home'); history.replace('/home'); history.push('/home', {state: state}); |
1 2 3 4 5 | // v6 navigate('/home'); navigate('/home', {replace: true}); navigate('/home', {state: state}); |
For the case you often use go
, goBack
, goForward
of useHistory
, with useNavigate
, everything is simplified:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | // This is a React Router v5 app import { useHistory } from 'react-router-dom'; function App() { const { go, goBack, goForward } = useHistory(); return ( <> <button onClick={() => go(-2)}>Go 2 pages back</button> <button onClick={goBack}>Go back</button> <button onClick={goForward}>Go forward</button> <button onClick={() => go(2)}>Go 2 pages forward</button> </> ); } |
With v6:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | // This is a React Router v6 app import { useNavigate } from 'react-router-dom'; function App() { const navigate = useNavigate(); return ( <> <button onClick={() => navigate(-2)}>Go 2 pages back</button> <button onClick={() => navigate(-1)}>Go back</button> <button onClick={() => navigate(1)}>Go forward</button> <button onClick={() => navigate(2)}>Go 2 pages forward</button> </> ); } |
5. From 20kb to 8kb
More than all of these changes, React Router v6 is smaller and only 50% lighter than the previous v5 version. Lighter means it will load and load libraries faster. Too great.
https://bundlephobia.com/ [email protected]
https://bundlephobia.com/ [email protected]
6. Summary
Through the above article, I want to introduce the highlights of React Router v6 compared to the current version, v5, hoping to help everyone.
Let’s wait for the official release of React Router v6, release note
Thanks for watching.