Routing
set up
use react-route-dom package
Wrap the App with BrowserRouter
<BrowserRouter>
<App />
</BrowserRouter>
Route
-
render:
<Route path="/" exact render={() => <div>Home</div>} />Attention: without
exact, it will match the routes that have/, which means all the routes. -
component:
<Route path="/posts" component={Posts} />
Switch
find one of its children, from top to bottom, to fit the current url.
This means that you should put <Route>s with more specific (typically longer) paths before less-specific ones.
<Switch>
<Route path="/posts" component={Posts} />
<Route render={() => <NotFound />} />
{/* <Route path="/" component={Home} />*/}
</Switch>
Route info
The information of Route, like match.url, match.params is passed into the component as props.
While the children components haven't access to this info, we use withRouter.
export default withRouter(ChildComponent);
Link
instead of using <a>, which will reload the whole app, using <Link> to navigate inside the app.
<Link to="/">Home</Link>
<Link to={{
pathname: "/search",
hash: "#search",
search: "?quick-submit=true"}}>Search</Link>
Linkof react-route-dom wraps<a />.
<NavLink /> adds active class to Link, we can style the Link by CSS:
a.active {
color: red;
}
We can override the name of class by activeClassName:
<NavLink to="/" exact activeClassName="home-active">
a.home-active {
color: red;
}
activeStyle can set the inline-style of NavLink
absolute vs relative path
-
absolute
<Link to="/" exact>Home</Link> -
relative
add
/1after the current url<Link to={this.props.match.url + "/1"}>Page 1</Link>
Route params
<Link to="/post/new" exact>new</Link>
<Link to="/post/:id" exact>post</Link>
Put the route with params at the end of all routes, avoid pass new to :id
to extract route params, we can use props.match.params:
// Home.js
<Link to="/post/:id" exact component={Post}>post</Link>
// Post.js
componentDidMount() {
const id = this.props.match.params.id;
}
navigating programmatically
props.history.push('/post/new');
which navigates to a new page.
Redirection
<Redirection from="/" to="/posts" />
redirect after post created
postHandler = () => {
this.setState({
redirect: true
});
}
render() {
const redirect = <Redirect to="/posts" />;
return (
<Fragment>
{this.state.redirect ? redirect : null}
<div>Something else</div>
</Fragment>
);
}
redirect vs push
this.props.history.push('/posts') can also change the page, but:
-
push just add the new page into stack. We can click back to return the current page.
-
redirect can the remove the current page in the stack, and add the new page into the stack
redirect is equal to
this.props.history.replace('/posts')
Guards
There hasn't a Guard which is like the one in Angular, but we can control is in 2 ways
-
render
{this.state.isAuth ? <Secret /> : null} -
redirect
componentDidMount() { axios.get('/secrets-access').then( res => { if (!res.data.isAuth) { this.props.history.replace('/non-secret'); } } ) }
Lazy Loading
To load the components asynchronous, use React.lazy & Suspense
Like React.Fragment, React.lazy & Suspense is for React 16+
// import Post from '../Post'
const Post = React.lazy(() => import('../Post'));
render() {
return (
<Route
path="/post"
render={() => (
<Suspense fallback={<div>Loading...</div>}>
<Post />
</Suspense>
)}
/>
);
}
or, we can create our HOC lazy: lazyComponent
to use it:
const LazyPerson = lazyComponent(() => import('./Person/Person'));
const lazyPerson = (
<LazyPerson
name={this.state.name}>
<span>lazy</span>
</LazyPerson>
);