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>
Link
of 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
/1
after 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>
);