×
By the end of this chapter, you should be able to:
Switch
withRouter
and Redirect
to implement redirects in ReactVery commonly with routing, you will want a 404 handler for routes that do not exist. To do this with React Router v4, we use a component called Switch
to wrap our routes. Switch will render the first child <Route>
( or <Redirect>
, which we will see in a little bit) that matches the location.
You might be wondering, how is this different than just using a bunch of <Route>
components? The answer is that <Switch>
renders a single route inside of it. If multiple <Route>
components match the path inside of a <Switch>
, only the first one will render.
Consider this code:
import React from "react"; import { BrowserRouter, Route, Link, Switch } from "react-router-dom"; const NotFoundExample = () => ( <BrowserRouter> <div> <ul> <li> <Link to="/">Home</Link> </li> <li> <Link to="/will-not-match">More 404!</Link> </li> <li> <Link to="/dsajkdjsaldjskla">404 time!</Link> </li> </ul> <Switch> <Route path="/" exact component={Home} /> <Route component={NotFound} /> </Switch> </div> </BrowserRouter> ); const Home = () => <div>Welcome home!</div>; const NotFound = ({ location }) => ( <div> <h3> No match for <code>{location.pathname}</code> </h3> </div> ); export default NotFoundExample;
You can read more about Switch
here.
So far we have seen how to set up React Router with different types of routers, we've created routes, and we've passed props to our routes. This is a great start, but we're missing another essential concept with routing - redirecting!
When we redirect in a single page application, we are not doing the same thing as a normal HTTP redirect, which involves sending a location header and making a GET request to the value of that location header. We are simply making another AJAX request to load the correct information when we redirect.
With React Router v4 we are given access to a Redirect
component which is useful for conditionally rendering or redirecting. We can also redirect with the help of a higher order component called withRouter
, which will allow any component to access the router props.
withRouter
to redirectIn the last chapter, we saw that when you write code like this:
<Route path="/" component={SomeComponent} />
then SomeComponent
will have access to the three router props: match
, location
, and history
. In particular, because it has access to the history
prop, it's possible to issue a redirect, using the push
method on history
and supplying a new path. We'll see a code example of this momentarily.
This is great if you want to issue a redirect from SomeComponent
. But what if you want to redirect from a component that isn't passed into Route
, and therefore does not have access to the router's props? Fortunately, React Router solves this problem by providing us with a higher order component called withRouter
. This function wraps a component and returns a new component which has access to the router props! Let's look at an example of an app that uses
history.push
to issue a redirect on a button click.
import React, { Component } from "react"; import { Route, Link, withRouter } from "react-router-dom"; const Data = () => <h1>You made it!</h1>; class Button extends Component { constructor(props) { super(props); this.handleClick = this.handleClick.bind(this); } handleClick() { this.props.history.push("/data"); } render() { return ( <div> <button onClick={this.handleClick}>Click me!</button> </div> ); } } const App = () => { const RouterButton = withRouter(Button); return ( <div> <h2>Let's show the data component!</h2> <div> This button won't work! <Button /> </div> <div> This button will! <RouterButton /> </div> <Route path="/data" component={Data} /> </div> ); }; export default App;
Along with withRouter
, there is another way to redirect using the <Redirect/>
component. Here's a quick example:
import React from "react"; import "./App.css"; import { Route, Link, Switch, Redirect } from "react-router-dom"; import ParamsExample from "./ParamsExample"; const Private = () => ( <div> <h1>GO AWAY THIS IS PRIVATE</h1> </div> ); const Public = () => ( <div> <h1>hello! so nice to see you!</h1> </div> ); const FeelingLucky = () => { const to = Math.random() < 0.5 ? "/public" : "/private"; return <Redirect to={to} />; }; const App = () => ( <div> <ul> <li> <Link to="/public">Public Page</Link> </li> <li> <Link to="/private">Private Page</Link> </li> <li> <Link to="/lucky">I'm Feeling Lucky</Link> </li> </ul> <Route path="/public" component={Public} /> <Route path="/private" component={Private} /> <Route path="/lucky" component={FeelingLucky} /> </div> ); export default App;
In this example, the /lucky
route redirects to either /public
or /private
, depending on the size of a randomly generated number.
You can read more about <Redirect/>
here.
Take a look at this example in the React docs and work your way through what is happening. Click around and see what the code on the right is doing.
When you're ready, move on to React Router Exercise