[React]: Router with React Router DOM
React
11/06/2019
More information on React Router DOM can be found here.
1. Install React Router DOM
npm i react-router-dom
2. Add Browser Router in index.js
// ...import { BrowserRouter } from "react-router-dom"
ReactDOM.render( <BrowserRouter> <App /> </BrowserRouter>, document.getElementById("root"))
Import Browser Router component and wrap it around the App component.
3. Create Route in App.js
Import Route
import { Route } from "react-router-dom"
Create another page
const MainPage = () => ( <div> <h1>MAIN PAGE</h1> </div>)const SecondPage = () => ( <div> <h1>SECOND PAGE</h1> </div>)
Create route
function App() { return ( <div> <Route exact path="/" component={MainPage} /> <Route exact path="page2" component={SecondPage} />> </div> )}
Note: If you don't put exact, it will be rendered in different pages as well which includes the same path.
For example, if you would like to include a navigation bar in all the pages exclude exact tag.
4. Using Switch
Using Switch component prevents from rendering other pages.
import Switch Component
import { Switch, Route } from "react-router-dom"
Usage
function App() { return ( <div> <Switch> <Route exact path="/" component={MainPage} /> <Route path="/page2" component={SecondPage} /> </Switch> </div> )}
When a Route is found inside Switch tag, it won't render anything else.
For example, when we have
<Switch> <Route path="/" component={MainPage} /> <Route path="/page2" component={SecondPage} /></Switch>
Then, we go to /page2, it will only show MainPage since MainPage will be rendered and it doesn't render others.
Creating Dynamic routing
Nested routes
Creating nested routes is possible with the following.
First, create more sub page
const SubPage = () => { return ( <div> <h1>SUB PAGE</h1> </div> )}
function App() { return ( <div> <Route exact path="/" component={MainPage} /> <Route exact path="/page2" component={SecondPage} /> <Route path="/page2:pageId" component={SubPage} /> </div> )}
:pageId is a URL parameter. It shows the pages that match dynamically. For example, it will show the SubPage for any url: /page2/*
props components
props has different components:
- props.match
- props.history
- props.location
We can show which url that's visited with
const SubPage = props => { return ( <div> <h1>SUB PAGE: {props.match.params.pageId}</h1> </div> )}
For example, when we visit
localhost:3000/page2/asdfasdf
It will show on page:
SUB PAGE: asdfasdf
This allows the sub page to populate itself. This may be useful to retrieve data from back end.
Link Component
import { Route, Link } from "react-router-dom"
const SecondPage = props => ( <div> <Link to="/page2/100">To Sub Page 100</Link> <h1>SECOND PAGE</h1> </div>)
Note: React is SPA. This does not redirect and rebuild the entire application, but rather, it determines which part of the DOM to use.
This would be similar to using:
<button onClick={() => props.history.push("/asdf")}>Click</button>
By using a props component it'd be more efficient to use it as:
const SecondPage = props => ( <div> <Link to={`${props.match.url}/100`}>TO SUB PAGE 100</Link> <Link to={`${props.match.url}/222`}>TO SUB PAGE 222</Link> <Link to={`${props.match.url}/7`}>TO SUB PAGE 7</Link> <h1>SECOND PAGE</h1> </div>)
This is useful when you want to re-use sub page that isn't from page2.
For example:
function App() { return ( <div> <Route exact path="/" component={MainPage} /> <Route exact path="/page2" component={SecondPage} /> <Route path="/page2:pageId" component={SubPage} />
<Route exact path="/asd/asd" component={SecondPage} /> <Route path="/asd/asd/:pageId" component={SubPage} /> </div> )}
SecondPage and SubPage components can be re-used in different links in /asd/asd.
withRouter
As we've imported React Route in our app class, in order for sub-component to use it, it would have to pass down props.history. However, there may be situation where you have to pass down the props.history multiple times--this inefficiency is called prop tunneling/drilling.
To prevent this, in the children that needs props.history, use the component withRouter.
Usage
import { withRouter } from "react-router-dom"// ...export default withRouter(ChildComponent)
withRouter is a higher order component, function that takes any component as argument and returns a modified component.
i.e. the child component gets access to props.history
In the child component, access with
<div className='' onClick={() => history.push(...)} >