Importance of Natural Resources

Programmatically Navigate with React Router

In this video, what we’re going to do is we
are going to learn how to programmatically navigate with React Router. What that means is, typically the way that
your user navigates around your app is by clicking on a Link component, but sometimes
what you want to do is you want to navigate the user based on a specific action. So for example, here what we have is we have
this Register component, and you’ll notice it’s rendering an h1 as well as a Form. And then when the user submits this form,
this handleSubmit function is going to be invoked. We’re going to call saveUser. We want to save the user, and then we want
to redirect the User to the Dashboard. So, there is a few different ways that we
can do this with React Router and we’re going to kinda compare and contrast both ways. Before we do that, what I wanna talk about
is kind of the main ideas behind React. If you broke down React into basically three
concepts, what you get is you’d get Component composition, Declarative UI, and you’d get
this cycle right here when there is an event. That triggers some state change and then you
go ahead and re-render your app. What I really like about React Router is its
dedication to Declarative React-like code. Code React Router v4 truly is a React router. The whole goal of the redesign to React Router
v4 was to align React Router’s vision with React. What that means is that React Router was really
aligning themselves with these three principles right here, Component composition, Declarative
UI, and then this process right here. And this really shows when we look at the
first and really the recommended way to programmatically navigate in a React Router app, and that is
with a Redirect component. So, what we’re going to do here is we’re going
to go ahead and import Redirect from react-router-dom. And now, what we need to do, just like we
do with any other component, we wanna go ahead and render this component, specifically the
Redirect component, when we want the user to be directed to another route. Now, it’s going to feel really weird because
what we’re going to do is… Let’s come up here and we will say, “If this.state.toDashboard
is true, then what we want to do is we want to render that Redirect component,” and we’ll
pass it a ‘to’ prop that just says, “take the user to the dashboard route.” Again, this feels weird, but if you think
about really what React is, it’s these three things. And by having a Redirect component and rendering
it, it feels very React-like. We have some composition. We have Declarative UI and we also get this
process right here where we’re going to trigger an event specifically, the User Registering. That’s gonna change the state. We’re going to cause a re-render which will
then go and take the user to the dashboard route. So, let’s go ahead and take a look at what
this is going to look like. You’ll notice that we added a state…a property
to our state. So, we’re coming here and we will say, “toDashboard
is going to be false, and then when this handleSubmit method is invoked, the very first thing we
want to do is call the saveUser function.” We’ll pass it user, that’s going to return
as a promise. And then, just like we’ve always done, we’ll
call setState and then we will change toDashboard to be true. So really, what’s happening here is whenever
the user submits the Form, we save the user. We flag or we toggle toDashboard to be true,
that will cause a re-render, and then we will redirect the user to the dashboard route. Again, redirect is composable, it’s declarative,
and it follows this process. Now, what are the downsides of Redirect? You might still hate it at this point. The most often heard criticism is that you
need to create a new property [inaudible 00:04:03] the state in order to know when to render
the Redirect component. So here, what we did is we added this toDashboard
property, and if we weren’t using Redirect, we wouldn’t have to worry about managing the
component state. But really, that’s kind of the whole point
of React, the state changes and then we update the UI. It is more typing but naturally, by explicitly
defining and modifying your state, you have to type more. The main argument for the Redirect component
is explicit state leading to a declarative APIs better than implicit state handled by
an imperative API, but enough now. Let’s go ahead and look at another example
now. You may have heard of the history package. It’s really the thing under the hood of React
Router that’s doing all of the work of keeping track of the session history of the application. When a component is rendered by React Router,
that component is going to be passed three different props, location, and match, and
a history prop. And it’s this history prop that we’re going
to use to redirect if we’re not using the Redirect component. So, what we will do is let’s go ahead and
get rid of this property on our state because we won’t need that. And then, we will also get rid of the sign
right here. And then now, assuming that this Register
component was rendered by React Router, and we’re getting those three props, location,
match, and history, what we can do is when saveUser is called we get a promise back. And then, what we can do is we can go ahead
and call this.props.history.push, and we can tell it where we want to go. We want to go to the dashboard route. So, it’s pretty straightforward. It’s an imperative API. So, some would argue that it is worse, but
it is a lot less typing, and it’s pretty straightforward. Once the user is safe, we can go ahead and
call history.push going to the dashboard route. Now again, this only works if we’re being
passed a history prop. If we’re not, then this prop.history is going
to be undefined which obviously, won’t work in this case. But if you want to use history.push but your
component isn’t being registered or isn’t being rendered by React Router, what you can
do is you can import this withRouter higher-order component. And we can get rid of Redirect. And then now, what you can do is on your export,
you can go ahead and just say, “export.default.withRouter,” passing in your component. And then now, React Router is going to go
ahead and make sure to pass this registered component the three Router props, history,
match, and location. So then, you can go ahead and call this.props.history.push. So, there you have it. There are two ways to programmatically navigate
with React Router, Redirect and history.push. Whatever one you use, it’s mostly up to you,
whatever you feel most comfortable with. I try to always use the Redirect component
but if you just feel like it’s too much typing or it’s not worth the hassle, go ahead and
use history.push.

Reader Comments

  1. Thank you Tyler, so much better to just youtube problems where you can see the problems clearly laid out vs stack overflow

  2. <Redirect to='/dashboard'/> needs to be returned from inside your conditions, otherwise nothing is going to happen. So correctly:
    if (this.state.toDashboard === true) {
    return <Redirect to='/dashboard' />

    Apart from that, this is a great tutorial! ๐Ÿ™‚

  3. I was confused with the online resources and thanks for the clarification. ALL IT NEEDS is just a change of this.state…

  4. i thin kyou really miss something with your tutorials. You show how to re-route but you forget how to use props on , the "Dashboard component". ๐Ÿ™‚

  5. Hello, does anyone know how I could do this.
    I have an api with all data from profiles. with the arrow keys I need to be able to click through a profile accordingly.
    The data in the form above me is always changing when I click on a left or right arrow.
    Can this be done with react-router?

  6. Thank you soooooooooo much – been stuck and the withRouter part around 6:30 in the video allowed me to conditionally render the component.

  7. In case if you import { connect } from redux
    the synthax should be like this:

    export default withRouter(connect(mapStateToProps, { addCart, getCarts, updateQuantity } )(ProductDetail));

  8. ๐Ÿš€ Try our new 2019 React Course –

Leave a Reply

Your email address will not be published. Required fields are marked *