In this lesson we'll create a protected route just for logged in users. We'll combine a Route with a render prop and use a loggedIn prop to determine if the route should be allowed to be accessed. Finally we'll use nav state to preserve the location the user visited and redirect them back to the protected route once they login.
Instructor: [00:00] We're starting off with a home and a profile setup. The home and the profile look like this. There's a home and a profile that we want to protect with the user having to be logged in.
[00:13] In order to do that, we're going to create a protected route. The protected route is going to be a normal React component. We'll say, const protected route, and we're going to need to destructure a few things.
[00:29] The first is going to be our component, which we're going to call comp. We're also going to destructure loggedIn path, and put the rest of the props on a variable called Rest. Then, we're going to render a route. We're going to say, return route. We're going to pass in our path, spread the rest of our properties that were for the route on top of that.
[01:05] To do the protected route, we need to use a render prop. We're going to say, render, which will inline a error function. Which will then receive the props that we need to pass down to our component.
[01:22] We can then return our comp and spread our props on. We've now essentially created a normal route that receives a component that we render, then pass our other navigation props onto.
[01:41] But what this render prop gives us is the ability to match a route and do some logic. That logic's going to look at loggedIn, then determine what we want to do. We're going to use a ternary and say, loggedIn.
[01:58] We'll render our comp if we're logged in just like a normal route. Otherwise, we'll use the redirect. We'll say, redirect to /. We'll redirect back home, which will then match our home route.
[02:19] Now, if we take our protected route, and we place it here, instead of using a normal route, we use a protected route. We go look at that in the browser. If we click on our profile, you'll see that it quickly matched profile but redirected back to home.
[02:34] This is not the ideal interaction, because we want to inform the user that they've gone somewhere that they're not allowed to go. The to property of redirect also takes an object.
[02:46] We're going to say, pathname = /, to redirect back to our /. Then, we're going to add some navState. NavState will then be able to be passed along to the route that we redirect to.
[03:01] First off, we're also going to add our previous location. Our previous location will be our current location, we can then redirect them back to where they attempted to come from. That is a good user experience.
[03:13] We're going to path onto here, and we're also going to add an error. We're going to say, "You need to log in first." Now that we are passing along our error, we can now render it in our document.
[03:30] First off, we're going to need to destructure it from our location. We're going to say, const state = an empty object, just in case it's undefined. Say, this.props.location. Then, we'll destructure error from state.
[03:47] Here, just above our routes, we can say, error. Then, we'll render a div with error and render our error. If we take a look what that looks like, we click on profile, that requires us to be logged in. Then, it redirects us back to home. Now, we have our error rendering.
[04:11] Except now, we need to add the ability to log in and redirect them back to where they came from. Here, we're going to add a button, say, onClick = this.handleLogin. Say, log in, close off our button, then we will create a handleLogin.
[04:33] Generally speaking, it'll do something asynchronous here. But we're going to do a setState. We're going to first also destructure our previous location from our state. We're going to copy this, and rather than error, we want our previous location.
[04:53] We'll then do a this.setState and set loggedIn to true. However, we want to make sure that loggedIn state has taken effect before we trigger our change in location. Otherwise, we'll run into our redirect issue.
[05:11] We're going to use the componentDidUpdate callback for setState, and say, this.props.history.push to our previous location. Or, if our previous location is undefined -- because it could be potentially undefined -- we'll say, redirect to a default. Which will be our /profile.
[05:36] Before we test this out, we need to pass down loggedIn to our protected route. We're going to say, loggedIn = this.state.loggedIn. Now that we're passing to our protected route, it will destructure it. If it's true, render our route like normal. Otherwise, it will redirect us with all of the issues.
[06:04] If we go in here, we can take this. Let's open up a new tab, and we have a fresh navState. We click on profile, we get our error, "You need to log in first." When we click on log in, it'll setState to loggedIn true. Which then will render.
[06:23] We'll do a push to our previous location, which is our profile. There we have it. Now, we can go between home and profile just like normal.