Getting Started With Next.js And Client Side GraphQL Authentication
Building a GRANDstack Podcast App: Episode 4
In Episode 4 we get started with the Next.js React framework, focusing on setting up our frontend application to handle authentication with our GraphQL API.
Links And Resources#
- Code on Github
- Next.js Tutorial
- Neo4j Next.js Example
- Neo4j Next.js Example With GraphQL
- GraphQL VSCode Extension
Hi folks welcome to the neo4j live stream. My name's will, and today we are going to pick up from where we left off last time, working with the grand stack podcast application, so we've been working on building out the graphql api for our podcast application. Last time we implemented parsing, podcast, xml feeds and loading that data into neo4j and before that we implemented authorization and authentication in the graphql api layer. And today what i want to focus on is getting started in the front end of our application and to do that. We'Re going to use a react framework called next js, so next js, you can think of as sort of a batteries included, react framework. So next js takes react and adds a lot of common things that we need when building a real world react application. So things like a file based router, whereas we add new pages, we create new routes. That map to those nest also has an image optimization component, so that, instead of serving massive image files, those files are scaled according to the device we are requesting them on. There's an analytics piece built in to next as well. The server-side rendering aspect of next.js is really interesting, so we can render pages on the server and then we're serving actual html to the browser. Instead of having to wait for javascript to load uh on the browser which is kind of what we get out of the box with things like create react app, and this is good for performance, but also seo the the the data fetching aspects and data fetching considerations. Then, when we have server rendering is really interesting, uh so we'll see how we deal with loading data in server rendered applications with next.js, including fetching data from our api. What i want to focus on today, though, getting the graphql client-side authentication setup, so we've built out our graphql api and now we're going to start using next.js, and i want to get next.js set up so that we can sign in to our application. And then we can start making authenticated graphql requests using next.js. So that's what we will focus on today, so i think we'll we'll skip over things like. How do we add uh styling? How do we work with some of the different server side, rendering and server side generated and functionalities of next and instead focus on making authenticated graphql requests from the client cool? So, let's make sure we have everything running here so we should have. We have neo4j running so our database is running. Let'S take a look at our data model in neo4j really quickly, so whoops not db, schema statements. We just want db.schema.visualization and let's reset the styles, so we see our labels here there we go so we've got uh users that subscribe to podcasts those podcasts have episodes a user owns a playlist and then can assign episodes to a playlist. So if we take a look, let's take a look at our users. Here got two users: here's user, jenny, cat jenny, cat subscribes to a couple of podcasts looks like she has two playlists road trip and jogging and jogging has one episode of the accidental tech podcast. So that's the data we have in the database, i'm going to start our api application. Let me bring the chat up, make sure you don't miss that if you have any any questions, uh or or thoughts or any heckling, feel free to add it to the chat here. Okay, graphql api is running on localhost 4001 graphql and make this a little bigger. So we have, i guess, both unauthenticated and authenticated entry points into our api. So, for example, we allow anyone to search. So if you want to search for podcasts by search string, you can do that without being authenticated. However, if you want to say, get all the playlists or if you want to subscribe to a podcast or create a playlist, you need to be authenticated and to make an authenticated request. We do that first, with a mutation which is the login either the login, or i think we have another one that we created yeah, which is sign up so for already existing users. We have a login mutation that takes a username login as jennycat and a password. I think jennycat's password is feed me and then this is going to return a token. So, what's going on behind the scenes we've stored, the hashed insulted password in the database right. So we don't. We don't store the actual plain text: password uh, here's, the hashed password, and so maybe let's look at our resolvers [ Music ]. We just have those in index.js uh. We do so. Here'S sign up uh, so we hash the password. So this is the uh sign up. We want login, so this is the login resolver. So when we pass a username and password, we grab that user by username from the database, then we com, we hash the password provided at the mutation. Compare that with what's in the database and if it matches, then we generate a json web token. That is valid for 30 days, and then we can use that token. So this is the generated json web token and json. Web token is, is just like an encoded json payload. So we could actually copy this and go to jwtio and we can decode this and we can get the user id and the username the date. The token was issued and the date it expires. So that's the information encoded in the token which we can see right here, we've just added id and username to that token, okay, so we log in we have the token and now to make an authenticated request. We add a http authorization, authorization, header and so the value for that is bearer and then the value of the token. So now we can make authenticated requests against our api, such as playlists. So we can say show me all of the playlists owned by this user and so on. The graphql server we're using this token to find that user in the database and we will find any playlists owned by that user cool uh. A question from the chat. If we're going to use the new alpha your geographical update, not today um today, i want to focus on just the client side authentication, so we won't actually do anything with the server side graphql api today, but yeah we'll definitely look at that in the future. Okay, so that was just a little refresher of what we've built so far. So what we want to do now is start to build some front end components in our application. We said we're going to use next.js and what we want to do is basically replicate this graphql flow that we just went through. So i want to be able to sign in and then i want to be able to make authenticated. Graphql requests from our react application. So we're going to need to think about okay. How do we handle that sign in mutation? How do we then take that token and make sure that then the graphql requests we're making from the react application are using that token cool, so there's a few different ways to get started using uh next js by the way, if you've haven't seen the next js Tutorial before i think this is quite nice, next js.org learn drop a link to that in the chat um. This is a fun one. It sort of walks you through using next.js and gives us points as we uh as we go along cool. So one of the uh great ways to get started - let's see if it's mentioned on this page, no, is the create next app command line tool. So if you, if you've used, create react app, this is kind of similar or if you've used, create grand stack app. This is a similar idea, basically, a command line tool to help us get started with a skeleton template for our application with create next app. You can pass examples that point to either an example from the official nextgs repo or you can build your own sort. Of example that points to a github url there are actually, if we look at uh, not this one, we take a look in the next js github repo under examples. There are actually a couple of these already there's one with apollo, neo4j graphql and with neo4j. So we could just get started with these i'll drop a link to these in the chat too. So we could get started with uh with one of these that would skeleton out the neo4j connections and uh the graphql api in nexus itself. So so one thing that's interesting about next js is: it is a full stack framework which means that there's a next.js server and we can add routes to that server. So we could actually move our graphql api into the next.js application itself, which i think is something we'll do in a future episode, not not today, but anyway, if we want to get get started quickly with a skeleton showing how to use neo4j and graphql already with Next.Js we could just use one of those examples. I'M going to start us off a bit more from scratch. How can i zoom in oh, yes, sure thing? Is that better how's the code is the code big enough? That may be too big shout if that's uh, if that's not any better, uh okay, so i'm in the root here, i'm gon na run uh npx create next app and we'll just call it next app and i'm not going to use any any of those example. Starters, we're going to sort of build up from scratch here and uh see what sort of benefits we might get from using one of those starters. Okay, so that created the next app directory for us and if we do npm run dev, it says it's created a dev server on localhost 3000 cool. It looks like we've got a page here, so let's open the code up and next step. So here's what create next app created for us a package json the only dependencies in here are react, react dom and next and here we can see the npm scripts, so npm run dev, which is what i did just now next dev, so that creates the development Server, which has a really nice watcher so as i make changes to the code, we should see that hot reload on the client application, which is really nice, build for when we want to build our static assets uh. Typically we don't. We don't do this uh, except maybe when we're getting ready to deploy our application depending on how we're deploying it and then next start, which again is typically not something we do locally. This is going to start the next.js server and do a production build. Typically. This is what we run wherever we're deploying this if it's on uh, versel or netlifier or wherever, okay, so that's package.json, it's created this pages directory for us, which has an index.js app.js, we'll talk about that later and then in an api directory. We have this hello js, so we said earlier that nextgs is really a full stack framework, so that means we can add routes uh as well. So here we've created a route at slash, hello, oh no, we didn't did we uh. Is that? Oh, is that slash api, slash, hello, yeah there we go slash api, hello right, so the file based router is relative to this pages directory. So index.js. This is the the page at the root we were just looking at and then the api directory slash api. Hello runs this route, which is just returning a json object, so we could move our graphql api into this next.js api at like api graphql, we'll save that for a future episode. Perhaps okay. So let's take a look at the root here: um [, Music ]. So we have a head element: okay, so that's setting like the the title of the page uh and then we're we have the content of the page and a footer. Let'S, let's go ahead and take most of this out. Let'S take all of that out um. What did we do? There main? Oh, we didn't have a closing main there. We go uh and grand cast fm as you can see as we change things we don't have to refresh and that updates in the application. Okay cool. So the first thing we want to do is, i guess, maybe let's create a new page here - to test out the file based routing, so i'm going to create a new page called podcasts and in this page what we want to do is make one of our Uh one of our requests against the graphql api to just render uh - maybe a list of podcasts right. So this is one. This is one we can do without being authenticated. So i can make a request for all of the podcasts that i have in the database and maybe just render those in a list so to do that. We'Ll just create a simple functional react component called podcasts um. Let'S for now just return, dev and we'll say all of our podcasts are in this list here and then we need to export this, and now this page should be picked up at slash, podcasts cool. So there's our file based routing a question from renato. I notice you're not using typescript. Is there a reason for not using it um? No, not really um. I think you know if you're, if you're familiar with typescript um you, you can see the advantages where it comes in um. Typescript support is really easy to add. To nexjs, by the way, i think you basically just have to create like a blank ts, config and then that gets sort of automatically populated. So no there's no reason i'm not using typescript. I think typescript can sometimes kind of kind of get in the way. When i'm i'm sort of playing around and exploring um new things, so maybe maybe that's a reason but uh. No, i mean typescript is great. If you know, if you enjoy the benefits, you get from typescript great a lot of the the same concepts uh apply here, but i think you know for some applications. Typescript can be. You know a bit of a a bit of a burden. Some cases, especially especially in you, know, learning and uh playing around with new technologies. So yeah good question. I guess that's um, that's maybe why i'm not using it today cool. So now what we want to do is fetch some data to populate this list, and we know we want to fetch that data from our graphql api, so we're going to pull in apollo client, so apollo client is popular graphql clients there are. There are lots of different ways that we can make graphql requests from a react application to a graphql api. I mean at the end of the day it's just an http request and json coming back, so we can even use something like fetch if we wanted to the benefits that we get from apollo client, though, are framework level integrations with the state system of that framework. So in in react, uh we have react hooks that wrap the apollo client api that make it nice to integrate with with state in react and then there's also a apollo client cache that will uh cache our graphql request so that we're not unnecessarily loading data and Making unnecessary requests to the server so anyway that that's why i like to use apollo clients um in react. The first thing we need to do is install it, so i'm going to stop our server and do an npm install apollo client. Oh, i guess i also needed to install graphql. I think that's a peer dependency of apollo client, okay, so that's installing. What we'll need to do is inject the apollo client instance. So what i skipped over here is how we create an apollo client instance. So we basically point it at a graphql uri and specify what kind of cache we want to use. The standard is, is this in memory cache and then we need to inject that apollo client instance into the react component hierarchy, because we want to make use of the react hooks that are provided in our components. So here we're wrapping the app component or like the the root component with this apollo provider, so provider components and in react are a way to expose the context api. So the the context, api and react is, is kind of a way of uh passing through values. Kind of like props, so when we pass in props to a component, if, like a child component, needs those props as well, we might just like pass those through again. This is called prop drilling and the context api is a way of kind of avoiding this concept of prop drilling, where we're passing things in passing, values and props to our nested components, and instead we want to just make values available to every component in the react Hierarchy, that's the context. Api and provider. Components are a way to do that. So what we want to do is wrap our root level, app component with apollo provider, which will make the the apollo client instance that we create available in every component. The way that we do that in next js is with this underscore app.js file, where here, the component is kind of the highest level that we that we have access to so we want to do is create an apollo client instance and then wrap that component. This component with that apollo provider. So let's do that uh, we'll import apollo provider, uh apollo client. What else do we need the in-memory cache? We need the http link from apollo client. I think that's all we need and then let's create a function here. [ Music, ] create apollo client and the first thing we need to do is create the link so an apollo link which we s, which we don't need by default. I guess this example doesn't show it do we have one on this page uh down here we do here we go so a link you can think of as like the networking layer for apollo client um. So if we want, if anytime, we want to modify the uh graphql request uh and we use a link so a link sort of uh kind of like middleware, the networking middleware, i guess, is a way to think of it. So we can define these functions that get called anytime, that a request is made and what we are going to do. The reason we need a link here is because we are going to specify that authentication header, and so we need to do that using an http link, so new http link uh for now, though, let's just not https http localhost 4001 graphql. So this is the uri of our graphql api and then we're going to return. A new apollo client instance passing in the link and then the cache is going to be a new in memory cache and then our [ Music ] component. Here we are going to wrap with the apollo provider passing in the result of create apollo client, okay, so we've created an apollo client instance and injected that into the react component hierarchy using this apollo provider. So now, if we go into [ Music ] our podcast component, now we should be able to uh make use of apollo clients to make a request against our graphql api. So if we take a look here at the query, fetching in the documentation, the way we do this is with the use query hook. So we use the gql tag to create a graphql document, this just sort of parses the graphql query, and then, when we call the use query uh hook, we get back a loading state. So whether or not the query is still loading. If there was an error and any data that we got back so let's import use, query and the gql tag from apollo client and our podcast query our the graphql query. We want to run uh podcast and title right. So that's the query we made here. Oh, i have the graphql vs code extension install. That'S why it's asking me if i want to execute this query uh. I think i need to configure this first. I don't think that'll work yeah, let's get that configured, so the the graphqlvs code extension reads from like a graphql config file, graphql vs code extension, dot; graphql, that's our schema, [, Music, ], graphql, config file, configuration examples, graphql rc, yaml, yeah, okay, so in the root Of our project, so at at the top level i want to [ Music ], create a dot graphql, rc, dot yaml, and here i'm gon na specify uh what the schema. So the schema is in api, api source, schema.graphql, okay, cool source, schema.graphql, and so this is this is so that i can have syntax schema aware, highlighting uh in schema, where hinting and linting in my template tags here within uh yeah, sorry zoom in within uh vs Code, that's what it needs to read the schema file, so that now it'll say: oh well, you could also add these other fields and then the other thing i want, because i want to be able to execute these queries. I want the i want to specify the endpoint to execute it against uh. This is the javascript version, but i think the yaml equivalent, i think, is fine. So what is that extensions? Uh end points uh and then just like this. I think just the just want a default endpoint. The url is going to be http. Localhost is that 4001 graphql? I think yeah and let me drop the link to this in the chat too. If you search the the vs code, extensions for graphql. This is the the first one that comes up as well, so this gives you syntax highlighting for graphql files uh as well as any time you use the gql tag. You get this functionality once you've configured it to be able to execute graphql queries that you're typing and should give us uh schema, aware, hinting cool so within vs code. I'M able to execute that query that i have embedded in this javascript file, which is pretty cool. So these are the podcasts that are i've parsed so far in the database and remember we only add podcasts when a user uh subscribe. So you can. You can search the podcast uh api index that we're using for any podcast, but we only add them to the database when you subscribe to them. That'S why there's only a few in there uh cool, so we should also be able to do autocomplete. Although it looks like that's not working [, Music ] did i have the wrong path to my schema file: api source schema.graphql. No, that's right! Api source schema.graphql! Can it introspect, if i give it uh? If i give it the end point, can it go introspect that will that work title? No suggestions? Oh, i don't know. Well, the execute query. Part worked. That'S that's neat um! It'S good enough good enough for me something to something to play around with. I guess: um not sure why it's not giving us the autocomplete, but anyway um [ Music, ] back to back to executing our query so right. This is the query we want to use. Let'S we'll just pull in the title of the podcast: we have that that's fine um, so then in the component, we're going to say data from use, query and then in our unordered list. Oh l! U that should be l i for for list item not sure what l lus then here we're going to say. Okay, if we have that data object, then for each object in the podcast array map over that i like to use v for value in these maps. I don't know if that's helpful or not, but we're going to return a list item for each one. We need to give each one of these a key to help react re-render. These so we'll add a key prop and then the only field we have is title. Oh and i'm missing, uh parentheses, yeah cool, so let's go back to our application. Oh server is not running, npm run, dev cool and now we are pulling in data from our graphql api, great uh, okay. So that is part of what we want to do. So a couple things to to take note of here - i guess one is we said earlier - that next.js allows us to do server-side, rendering and a few different, a few different modes of server-side, rendering it's sort of this hybrid framework. We can do server-side generation. We can also do incremental static, rebuilds uh, which is really interesting um, but when we work with data um with data fetching, that means we have to then, if we're doing server-side rendering we can either make those requests on the server side um, either at build or Request time those requests come from the server or we can make those requests from the client, which is what we're doing here. So we are making the data fetching requests from the client here, we're not doing uh server data fetching uh. One thing it's important to point out so we'll we'll talk, maybe next time about the server side, rendering with data fetching and what that looks like. But what i want to tackle next are authenticated graphql requests, so we uh, maybe if we think of the root of our application. So i go to this grandcast dot, fm application, uh and you know it's a podcast app and the whole purpose of it is like saving subscribing to and saving podcasts. So i think, by default we want users to sign in so we might have some routes in our application that are unauthenticated, maybe for like playing an episode. It doesn't make sense to require authentication to play an episode we can link into that. We can also think of like uh seo cases right where we want to benefit from people finding our site by searching for for podcasts um, and we don't want to gate those from google by requiring a sign in, but for the main experience yeah. It makes sense to to sign in so in the index.js page here. What i want to do is handle user sign in and then, when a user is authenticated, i want to show them their episode feed. So we have a graphql endpoint. I think we looked at this a second ago that is yeah the episode feed. So this is an authenticated entry point, so i need to have already signed in. I need to have that token attach it as a authorization header to then show the user well here of all the podcasts that you subscribe to here are the most recent episodes for those podcasts. So that's what i want on this page, so i guess a few things i need to get. There is a form to take the username and password. So let's call this. This will be our sign in component um and we are going to make use of the use state from react. So if we're working with react state and we're going to create a state variable called username and we also get back a function for updating that state. Variable set username and then the same for password, and these are going to be just for working with our form, so we're going to [ Music ] return, um a form, so let's create a function up here called on submit. So when we submit the form this function gets past that event, we call event.preventdefault because we don't want to reload the page, but we do want to authenticate the user somehow using the values. So we want to take the username and password that they've given us. We then want to run that login mutate, graphql mutation, okay, so when we submit the form we want to execute that on submit function, then we'll need a couple inputs, just a text input uh for the username, oh and then we need the onchange handler for this. So this is a function, that's also passed an event and here's where we're going to call our update state function. This is the username, so we want to set the username state variable to whatever we're typing in that input, and then we also need one for the password place. Holder is password and similar on change is now going to be set password to update the password state. Variable and we need a button log in um, okay, this is what we call this sign in. So let's render that cool, username password button, it's not going to do anything yet um, because we need to figure out how to run that mutation, uh and then the other thing [ Music ] we want here is: let's call this the episode feed component - and here We'Re going to make our graphql request feed query equals gql, [, Music ], so the graphql query we want to make is episode, feed, let's grab, i don't know what maybe like the first 50 um episodes and then we can bring in id title audio. That'S the audio file and we want to know the title of the podcast that it came from and remember this. This is an authenticated request, so we need to make sure that we have the user signed in before we can make this query um. Okay, so we'll say, use query, feed, query and then return, let's say episode, feed and then something similar to our podcast list. Let'S just have an unordered list and in the case where we have data uh for each episode. Let'S map over that and return. A list item [, Music ]. We use the id of the episode since we brought that back and maybe just the for now just the title: uh, okay and we can render that component as well. That is what did we call that episode feed? Oh gql is not defined. Oh yes, we need to import gql and use query from apollo client cool. So our episode feed is blank. We can verify that we're actually making the graphql request. If we go to the network tab do a refresh um. Here'S our graphql request and the response is empty, so no episodes because we're not signed in so this user. There is no user really to look up, subscribed episodes uh okay, so we now need to handle this sign-in mutation. So we could. We could implement that here. In this component, and just you know the user types in their username and password, we send that to the graphql api we get back a token, but then the question is then what so? We have the token um. If we do that in this index component, we'll like have the token, but we need to get that token up here so higher up in the react component hierarchy. We need it here in this http link, because this is where we need to specify the headers that we want to add to to our graphql client requests. So we have a little bit of state to to think about here right because we also have we want to have the ability to make unauthenticated graphql requests. So when we're not signed in there's no header to add, go ahead and send that. But when we are signed in, we need to keep track of yep. Here'S the auth token for this user and add it here. So i think what we'll do is add: let's create a new directory here in our next app i'll call this lib and let's create a new [ Music ] file. Let'S call this auth dot js and what i'm going to do is create an auth provider. So we'll we'll make use of the react context api to keep track of our authentication state, and then we will then have some helpers. Some helper authentication functions that will then be available within any of our components, so we'll be able to have like a login function. Here that we can export from this auth provider, that will then allow us to execute that graphql mutation to sign in and then also keep track of the token we should be using for our apollo client instance. So i'm going to import from react, we're going to be dealing with state we're going to be dealing with the context api, so we'll need a few imports here and then we're also going to be importing things from apollo client um. Should we just copy that, let's just copy this, since we already wrote that copy our imports for apollo client and that function for creating an apollo client instance? Okay, so the first thing i'm going to do is create this auth context. So we said earlier that the context api in react allows us to have, i don't know, maybe global um data is a good way to think of it, but data that's available values, functions that are available to every component. So then, from here we want to export an auth provider, which is what we're going to use to hook into the react component hierarchy. We'Re going to wrap our sort of top level app component with this auth provider, just like what we did with apollo provider um and in here we're gon na say that auth equals uh use provide auth. This is, this is something we haven't defined yet we'll define this in a moment and then what we're going to return is our auth context provider. So here we created this context, so we want the provider component on that and what do we want to make available? Well, we want to make available, are auth hook which we're about to implement um and then children right. So all our child elements, so we're that's our auth provider and then what are we missing? We want to export a hook, we'll call use auth. So this is what we're going to import in our components to access any of this auth context. This is going to turn the use context, call to auth context, so we're going to expose the context we're creating here to all of our applications or all of our components. Okay, and now we need to implement this use, provide auth. This is where most of that logic is going to live oops. Do this as an arrow function. Just do it like this? That'S fine, okay! So now the actual sort of auth logic that we want to implement um. Well, we said we want to keep track of some state here. So one thing we want to keep track of is what our auth token is so we'll create a react state variable to keep track of this called auth token and initially that'll be null um. What else we we need to create our apollo client instance? Let'S, let's move this, that we copied from our underscore app js file. Let'S move that in here so create apollo client is going to yep, create an http link, pointed at localhost 4001. Slash graphql create a new cache yep that looks good, but the other thing we want to do here is in the case where we have an auth token. So if we have an auth token, then we want to add that auth token to our headers. So, let's create a function, called get auth, headers and we'll say if we don't have an auth token return null otherwise return. This object, authorization bearer and then our token. So then, when we create our apollo client instance, we want to say that in the http link the headers are set by a call to get auth headers. Okay. So now, if we have an auth token, we'll add that as a bearer token, if we don't, then we won't add any headers and the other thing we want to do is now here previously we were creating apollo client in underscore app.js, so we'll delete the apollo Provider instead, what we're going to do is import the auth provider from our lib directory and we're going to wrap our main app component with the auth provider um. What that means. We get an error um because we can't find apollo clients yep, that's fine, but what that means now is that we want to inject apollo clients here as well, so [, Music, ], we'll wrap the child components also with apollo provider, and the client is going to Be auth, so that's a call to use, provide auth down here, dot create apollo client and we want to make sure that wraps our child elements there, yep cool uh, cannot read create element of undefined. Why is that? Oh, that's because we uh we need to return. [ Music ] from this use provide auth function. We need to return anything that we want to make available. So in that case, definitely the create apollo client function. Um. I think that's all for now: okay cool! So now we're creating our our apollo client instance. In this auth provider and injecting it into the react hierarchy there, let's make sure we didn't break the unauthenticated case. So if we go to slash podcast yep cool now we're making a request to the graphql api um and getting the list of our podcasts cool. So the next thing that we need to implement in our auth provider is some way to handle the login mutation. So we have this form and the form handler is this on submit function here. So what we want to do is take the username and password and we want to call the login graphql mutation to verify that get our token back and then update the auth token here, which is now a state variable in our auth provider. So to do that, i think we will let's create a function here. Let'S call it sign in it's going to take a username and password and we're going to use apollo clients to execute this mutation. So i guess we'll create a new apollo client instance here since i, because we don't have access to the one we create up there. That'S probably fine. We should probably cache it somewhere, but that's okay, uh. Okay, so we create an apollo client instance and then we need to know the mutation that we're gon na execute uh. Let'S, let's just build that here so mutation. Let'S call this login mutation we're going to need to use some graphql variables, so we'll say that username is a non-nullable string and password is also a non-nullable string and then we're going to use the login mutation passing in username and password from our graphql variables. Let me move this to the side, so we can see where type in and then our selection set um. I think the only thing yeah all we get back is a token um. Let'S test this query variables: let's define a username jenny cat password feed me. If we run this, do we get a token yes cool? So this, let's copy this um. This is the mutation. We want to run. Call this login mutation, that's the mutation. We want to execute um now for apollo clients. We can just use the the core api here, um apollo client. Is there a mutate, uh yeah? Here we go mutate, so mutate takes the options, object, which includes the mutation and variables yeah cool. So, let's make this an async function and we'll say the result equals await client.mutate and our the mutation we want to execute is login mutation and the variables are just going to be the username password that are passed into this function: okay, [, Music, ], let's, let's Just log the result for now what we need to do is grab the token out of this result, object and then call set auth token up here call set auth token to update this auth token, because it's a state variable that will update the auth header here. So then, we'll start making authenticated graphical requests um, but let's test this first. So let's add this to our exports here and now. If we go into index.js, we should now be able to import use off from lib auth.js and then in our form. Let'S see in the sign in component, i guess we want to [ Music ] grab the sign in function that we just created from the use auth hook that we just imported and then when we, when we submit the form we want to pass in the username And password these are the state variables here that are bound to the value from the form. So let's go back to our application, we'll sign in as jenny cat, let's open up our console, we see. So what should happen is we should log our token um? Instead, we get back gql is not defined uh. So let's import that here in our auth provider and let's try this again. Jenny cat feed me cool and we logged something. We logged a data, object, login, token cool. So here's here's our token. So now what we want to do, let's go into our auth provider down here, so here's where we're logging it. So, let's, let's finish this out: what we want to do is just call set auth token. I guess actually, let's wrap this. Let'S say if if we have a result and there is - and we have data - and there is a login value, so if we actually have the token uh, only then should we call set auth token and it's gon na be result.data.login.token. Okay. So now, let's see what happens sign in jenny, cat feed me hey. Now we have a list of episodes cool. So so what happened there? Let'S um bring back the javascript console. Let'S do a hard refresh to clean that out and go into the network tab here. So we can see that this first graphql request that we made for episode feed oops. What did i do? [, Music ]? That'S not what i want clear refresh sorry about that uh. This graphql request. Um. The response is an empty uh, empty episode, feed result set because we didn't send a authorization, header where's, our request, header request, header, there's no authorization header here, i'm not signed in, but now zoom out. So we can see all the requests now i'm going to sign in and now we make another graphql request this one in the request: headers, we can see here's our authorization token and here's the response data. That is, our episode, feed cool. So we've now made we've milling the ability to sign in to keep track of that authentication state and the ability to make authenticated requests against our graphql api, which is pretty neat. One thing we could do, though, is let's implement. We did sign in let's implement a sign out so uh. What i want to do is test that i'm able to sign out log in as another user and that i see different podcast episodes. So when we call sign out all we're going to do is call the set auth token uh state function and to set that as null and then i guess we need in index. Let'S put this in the episode feed yeah. Let'S put this at the end of the episode: feed is maybe just a uh like a sign out button, maybe uh. So when we click the button, let's just call sign out sign out and that sign out function comes from. Are you the use of hook? Okay? So sign out, sign out is not a function. Ah because i'm not exporting it here sign out. Let'S try that again sign out okay. I'Ve signed out so note that uh the way that state changes and then triggers re-renders in react. When i sign out that changes, the auth token state variable, which triggers a re-render and because we're passing that in our http link to set that header in our graphql request that uh token in the header then goes away, which means we're making an unauthenticated request. We don't go up, don't get back any results, but we do trigger a re-render of that data. So there's another user that we have in the database, let's log in as johnny montana, and we should see yeah so johnny montana subscribes to different podcasts than jenny cat. So we get different episode, feed that we've rendered here, but i can sign out. We can sign in as different user and now we get that user's uh podcast feed cool. So i think that is what we wanted to cover today. So this was just um getting started with next.js being able to make requests from the client to render data from our graphql api. We implemented our sign. In mutation, we created a auth provider to keep track of our authentication state in our react, application and hooked that up to the way that we're making graphql requests with apollo clients. So we can make authenticated requests to our graphql api and render that data in our application cool. So i think we will uh call it good for the day there. If you missed the previous episodes, you can find those on the github readme for this project, which is currently grandcast dot fm. I did actually buy that domain name. Let me drop that in the chat, so currently, grandcast fm will take you to the github repo. For this project, the so all the code is here which i will uh, i will push our next js code up to this repo that we did today, but you can find the uh video recordings from the previous streams and also i've been writing these up. As blog posts uh, so you can also find these uh on my blog. Here'S, the the one that we did most recently, which i'll link in the chat um as well. So you can find the code, the recordings um and, if you prefer, to read through these in blog form, uh we'll we'll write that up soon um by the way, my personal blog site. This is also a next.js application. Fun tidbit cool! Well, thanks uh thanks for joining today, i don't know what we'll cover next week. I guess we could either we could either add some styling and maybe a ui component library to our application to make things start to look nice or we could take a look at some of the data fetching with server-side rendering and server-side generation. That might be something interesting to explore. Let me know, let me know on twitter, which i'll link my twitter here in the chat as well. Let me know uh what you think we should work on next, if we should work on um styles, if we should work on, if we should work on server-side rendering and data fetching. What would be interesting, let me know, but anyway, thanks for tuning in today and hope to see you again next week, uh on the neo4j live stream uh, we stream these to either twitch or youtube so twitch, if you're, watching on one or the other or twitch.tv Neo4J, which i'll drop a link to that, if you're watching on youtube, it's the uft youtube channel so uh, i do streams almost every thursday at two o'clock pacific time, uh so hope you can tune in uh next week uh, but thanks a lot for joining today. We'Ll see you next time cheers
Subscribe To Will's Newsletter
Want to know when the next blog post or video is published? Subscribe now!