Custom Protected Route Component in React

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
In this video, I'm going to show you how to build your own custom protected route component in React. This is a component that you would usually use whenever you want to protect certain pages or routes in your React application, and only allow a signed-in user to access them. This is something that is pretty common in a lot of React applications that have authentication, right? If you have authenticated users, you often want to protect certain parts of your application and only make sure that signed-in users can access them. So, get ready, get excited, because you are going to learn a lot in this video. Alright, let's begin. Let's talk about protected routes in React. So here in front of us, we have a very simple React application, as always. The only thing that's different about this application is that we have this piece of code here, which creates a router using the `createBrowserRouter` function from React Router DOM. React Router DOM, if you're not aware, is a very popular client-side routing library that you can use to implement routing in your React application. This video is not going to be a tutorial on React Router DOM, but don't worry about it, you actually don't need to have a tutorial, because really, the only thing that we're doing is we're just creating this router, which basically allows us to set a specific component on a specific path. Right, so here we have the index path, and here we have the signed-in path. We're rendering the HomePage component on the index path, and the SignedInPage component on the signed-in path. That's it. And then the only other thing that is different is here towards the bottom in this piece of code. The only difference is that instead of rendering our own custom component, we're using the `RouterProvider` from React Router DOM, and we're passing it this router here. What this is going to do is this is going to make it so that this router here can actually decide which component to render based on the path that we're currently on. Then, if we actually look at the implementations of HomePage and SignedInPage, you're going to see that they're super simple. This component literally does nothing besides render a simple welcome text right here. The SignedInPage is also the same; it does nothing besides render "Signed In." We're going to be using this text right here, this `<h1>` tag, to just differentiate which component we're actually on. For the purposes of this video, we actually don't need to implement anything else. We don't need to implement our own sign-in functionality. Instead, what we're going to do is we're going to manually set the user to be signed in or not. The only interesting thing in our application so far is this `AuthProvider` component right here. If I open this component, you see that this one has a little bit of logic. So what this component does, what this file does, is it first creates a context, an `authContext` here on line five, using the `createContext` function from React. If this is unfamiliar to you, I do have a whole tutorial video on `useContext` that you can watch to get yourself up to speed. Then here on line seven, we're actually defining the types of our `AuthProvider`. So this is this component right here, the main component that is being exported from this file. We're basically saying that the props of this component can have children. That's from `PropsWithChildren` here, which comes from React. And we're also going to allow this isSignedIn optional property, which, as I said, we're going to use to manually set the user to be signed in or not. Here in the body of the component, we're using the `isSignedIn` property to either set a user if it's true or set it to null if it's false. If you look here at the type of `user`, this is a very simple type. A user only has an ID. And then here at the bottom, we have a custom hook called `useAuth`, which basically just makes it easier for us to access the `authContext` because it makes the check for the undefined case, and then we'll throw an error if the context is undefined. Otherwise, it is going to return the context. Again, if all of this is unfamiliar to you, I have a whole video on `useContext`, where we actually implement all of this and I explain to you why we need a custom hook for our context. So now what we need to do is we need to create a protected route component that can wrap any page component like this HomePage component, and then we'll use this `AuthProvider`, we'll basically make a check for the user. And then if we have a user, we are going to proceed with rendering the actual component. So in this case, the HomePage. Otherwise, we are going to redirect to the sign-in page, and we're going to let the router basically handle the rendering of the component. We're not going to decide to render the SignInPage component in here, but actually, we're just going to redirect and let React Router DOM handle that for us. So let's come here to components. Let's make a new file and let's call this one `ProtectedRoute.tsx`. And here I'm going to export default function, protected route, and we're going to leave it empty for now. The first thing that we want to do is we need to create some props for this component because it will need to have children, right? This component is going to wrap the HomePage component and that's going to turn it into a protected route component. So we need to have children in this component. So we're going to come here and we're going to do type `ProtectedRouteProps` equals `PropsWithChildren` and import this directly from React. This will basically allow you to have children in any React component. And then we can come here and we can do children: ReactNode. And then we can type our actual, let me see, our actual props, `ProtectedRouteProps`, like so. And now to make the errors go away, we can just return the children. And now we have the basic version of our protected route component. Then what we can do is we can come back to main and directly wrap the HomePage with `ProtectedRoute`. Protected Route imported and then paste the HomePage and then save. So now if I open up the application and I check here the URL, we are indeed on the index path, and we see here "Welcome," which is coming directly from our HomePage component. I can refresh and we see "Welcome," everything is working. If I now go to sign in, we're going to see "Signed in" and our SignInPage component is also correctly being rendered. So now let's implement the logic of `ProtectedRoute` to check the user to make sure that the user is signed in. And if the user isn't signed in, we redirect to the sign-in page. So remember, in this `AuthProvider`, we have this `useAuth` custom hook that we can use to easily access the user in this context. So that's what we're going to do. We're going to come here, make a new line, and we're going to do `const user = useAuth()`, import this from `AuthProvider` and save like so. If I now hover over this user, this user can either be of type `User` or of type `null`. Because we have used this custom `useAuth` hook, we've basically gotten rid of the undefined case. So we can just assume that we're either going to have a user here or we're going to have null, which is basically what we set if `isSignedIn` is `false`. The second thing that we need is we actually need a way to navigate the user to a different page. And for that, we're going to be using the `useNavigate` function from React Router DOM. So I'm going to come here and do `const navigate = useNavigate()`, import this from React Router DOM directly. Now with this, we have everything that we need to actually implement our logic. We're going to be doing all of this in a `useEffect` because we want to basically make this check whenever this component mounts and then redirect the user if the user isn't there. So we're going to do `useEffect`, import this from React, we're going to set up our basic `useEffect` here, we're going to pass navigate and user because we'll need both of these as dependencies of the effect. And then all that we have to do is just make this check—and see, Copilot is being very helpful—if we don't have a user, we're going to navigate to sign-in. Now, here's where you have to be really careful when doing something like this. This code is actually not 100% correct. If you look at the type of `user` here, it can either be `User` or `null`, right? Going back to the `AuthProvider`, we either have a user or we have `null`. Here what we're doing is we're doing `!user`, we're not checking for `null` directly. So with this code, if the user, for some reason, ever ends up being `undefined`, `false`, `0`, or any other value that is falsey in JavaScript, this code is going to run. We don't want this to run; we only want this to run if the `user` is explicitly `null`, because that's how we configured it in this component right here. So what we have to do is we have to make that check explicitly. If `user === null`, then and only then do we navigate to the sign-in page. And there's actually one more thing that we have to do, we have to put in here as a second parameter, we have to give it `{ replace: true }`. The reason why we want to do this, so first of all, `replace: true` here is going to replace the entire history with this page. And this is going to prevent the user from pressing back on the browser, and then going back to the page that they were on previously, right? If the user isn't signed in, and this is a protected route, we basically just want to send the user directly to sign-in and not allow them to navigate to any other page. So now if I go back to the application, you're going to see that already we are on the sign-in page. But even if I go in the URL and manually change it back to index, I can go to index and it's automatically going to redirect me to the sign-in page, I can press back and I'm not being sent back to the index page, I'm always going to be on the sign-in page. This is how you build a simple protected route component. And then you can wrap any component that you want to have protected in your router, and you're going to get the same functionality. The benefit of doing it this way is that now all of this code is extracted into a separate component, and it's shared across all of your protected routes. If you ever need to make a change to the user—maybe the user is no longer going to be `null`—or if you ever need to make a change to this logic—maybe you want to actually check some property of a user—you can do it here in one place. And then you can make sure that all of your protected routes will have this updated. And also, by the way, using this pattern is not only beneficial for protected routes, but you can actually create any sort of route component and put anything you want in there, and have that automatically apply to all of your routes. Maybe you want some custom styling, maybe you want some custom functionality like logging something to the analytics on a page view, whatever you want, you can create a custom component and then wrap every route with it, and then have that shared behavior across all of your routes. If you enjoyed this video and you want to see more videos just like these, maybe videos that are a little bit shorter that look at a specific thing in React, be sure to leave me a comment down below. Also, leave a thumbs up to this video and also subscribe if you haven't already, because it would mean the world to me. And also here, you have a different video of mine that you can watch that YouTube seems to think that you're really going to enjoy. With that being said, my name has been Darius Cosden. This is Cosden Solutions. Thank you so much for watching, and I will see you in the next video. Ciao, ciao.
Info
Channel: Cosden Solutions
Views: 37,778
Rating: undefined out of 5
Keywords: react tutorial, react crash course, react developer, learn react, react hook, react hooks, react hooks tutorial, programming tutorial, react hooks explained, computer science, tutorial for beginners, react component, learn programming, web development, frontend development, coding for beginners, simple code, easy programming, react, react native, react router, protected routes react, protected routes react router
Id: eFPvXGZETiY
Channel Id: undefined
Length: 10min 58sec (658 seconds)
Published: Fri Jan 26 2024
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.