How to Use a Viewer Cookie to Automatically Log In a User

Our server is now able to help set and clear the "viewer" cookie in our client when we sign-in with Google. In this lesson, we'll modify our client such that it will use the "viewer" cookie to automatically log a viewer in when the app first renders and the cookie is available.

Project Source Code

Get the project source code below, and follow along with the lesson material.

Download Project Source Code

To set up the project on your local machine, please follow the directions provided in the README.md file. If you run into any issues with running the project source code, then feel free to reach out to the author in the course's Discord channel.

This lesson preview is part of the TinyHouse: A Fullstack React Masterclass with TypeScript and GraphQL - Part Two course and can be unlocked immediately with a \newline Pro subscription or a single-time purchase. Already have access to this course? Log in here.

This video is available to students only
Unlock This Course

Get unlimited access to TinyHouse: A Fullstack React Masterclass with TypeScript and GraphQL - Part Two, plus 70+ \newline books, guides and courses with the \newline Pro subscription.

Thumbnail for the \newline course TinyHouse: A Fullstack React Masterclass with TypeScript and GraphQL - Part Two

With the server now able to help set and clear the viewer token in our client app when we sign in, in this lesson we'll modify our client app such that it will use the viewer cookie to log a viewer in when the app first renders and the cookie is present. To help log the user in, we'll fire the login mutation we already have available in our API. Since we'll want to run this mutation when the app renders and regardless of which component or page is being shown, we'll have this mutation fire in the parent app component. We're interested in running the login mutation the moment the application first loads or in other words the moment when the app component first renders. To help conduct the mutation during this effect, we'll import and use the use effect talk. Since we're interested in using the login mutation, we'll import the login mutation document the auto-generated type values for the login mutation as well as the use mutation hook from React to Polo. We'll use the use mutation hook at the top of our app component and pass in the login mutation document. We'll simply return the login request function and the error result value. Similar to how we've achieved the login mutation in our login component, we'll state that when the mutation is successful, we'll set the viewer state value in our client with the returned data from our mutation and we'll use the on completed callback to do this. We'll use the use effect hook and look to run the effect only when the component first renders by using an empty dependencies list and in our effect callback we'll simply run the login mutation. To satisfy the use effect hook, we'll import the use ref hook, use the use ref hook and place the login request to create a ref object that is to remain constant to the life of the component. And then we'll access and run the login mutation from the ref object by using the current property. Next, while our user is being logged in, we probably want to show some loading indicator of sorts. The loading UI we'll look to show will be page level, where a skeleton of the app header is shown above and a spinning indicator is shown in the body of the UI. The skeleton of the app header will sort of improve the perceived performance of our app since the app header will show shortly after. Let's first look to create this app header skeleton component that we'll use. We'll create this app header skeleton in the lib components folder and re- export what we plan to create from the components index file. The app header skeleton component will be very similar to the app header component, except for not accepting any props and simply just showing the logo without any menu items. So we'll copy the code over from app header, make the modifications we want and also copy over our app logo asset. [silence] To show loading UI when the login request is in flight, we could use the loading value from the mutation results. But in our case, what we'll check for is the did request property of the viewer state object and the error state of our request. We know that the did request field of our viewer object will only be set to true when the viewer manages to either login successfully or unsuccessfully. So in other words, when the login request has been made complete. So we'll use the did request field to verify the the viewer has finished either logging in or attempting to log in. We'll also check for the error status of our mutation request. If at any moment the mutation contains errors, we'll stop displaying the loading indicator and we'll show a banner in our app with which we'll actually create shortly. With that said, if the did request field is not true and the mutation hasn't er red, our app components will show the app header skeleton and a spinning indicator that says launching tiny house. We'll import the app header skeleton components from our lib components folder. And import the spin components from ant design. If there was ever an error during the login process, we'll import and use the error banner component we've created before to show an error banner at the top of our app to notify the user. We'll use an error message along the lines of something like we weren't able to verify if you were logged in, please try again later. We'll set this error banner element to a constant we'll call login error banner element and have this element constant shown at the top of the app components. And that's it, that's pretty much all we'll need to do here. When our parent app component renders, it'll fire off the login mutation requests. As the request is fired, the necessary cookie is sent to the server automatically. If the viewer cookie is available and the server is able to locate the user in the user's collection from this viewer cookie ID, the server will return with this user with which the client app will then set the viewer state object with this returned user. In other words, the user will then have successfully logged in via a cookie. Let's give this a try. We'll head to our client application and we'll sign in once again. When successfully signed in, we're back in our app in the logged in state. When we now close the browser or close the tab, reopen it or even refresh our app, we'll stay in the logged in state. We can also see the brief loading indicator that says launching tiny house, which represents the in flight status of our login request via cookie. When we now log out of our app, the viewer cookie will be cleared from our browser and upon refreshing the app, we won't be logged in any longer. Amazing. [BLANK_AUDIO]