Adding Conditional UI for Authentication
Okay, so the first step in our sort of authentication pipeline is going to be a modification to nav.js. Right? So nav.js has essentially the responsibility to show a login box as well. So what I'm going to do, I am going to add that logic right in here. Now I'm going to add quite a bit of code, so don't be alarmed. We're going to go through that together, of course.
So let me just copy the right bit of code over, along with the register link. And theoretically that's all the code that I need. It has a couple of lines of code, as you can see. Now we do have some helpers like loading and then user. Where that comes from, I will tell you in just a moment. But you see that there's some conditional, inline conditional rendering happening here in Next.
And I say if we have a user, then please show me the profile menu item, otherwise show nothing.
Also, if there's a user, please show me the logout, although probably because these are the same, I could have grouped them together. But you know, do that as a homework maybe.
And then last but not least, I also have another use case where I say, if there's no user, I mean there's no active user currently logged in, then just add a form that is going to ask for a identifier and a password. And I have the handle change for both of those. You know, if you know React, then you know why that's there. And I also have this button that says login. And of course we have this handle submit method that we also need to write, that's going to be responsible for signing in a particular user. So we do need to write quite a bit of code.
Now, handleChange is going to be the one that we're going to start with. And as you can see, handleChange is for both of these cases, both for the input type text and for the input type password. And the reason why I can do that is because of writing some clever JavaScript that looks like this.
So I'm leveraging all the greatest features of ES6. I'm creating the properties programmatically. So now you can in JavaScript create programmatic property names. And so I take the value of the input box and I set the value. And because I'm building that up dynamically, it's going to be either relevant to the input box or to the password box. Okay, but this is still just React. Okay, there's nothing Next.js specific. This behavior in Next.js is, you know, React essentially under the hood superpowers.
Now, we do need to also specify the useState hook because we want to keep track of data and set data. So I'm going to call useState and we're going to instantiate the state, again, not like that, but just from React, using an object where we're passing the identifier. I'm going to instantiate that to be empty. And then the password is also going to be empty, like so.
Okay, so we have that.
Submitting Login Data to Strapi
And let's now add the handleSubmit function, which is going to be an asynchronous arrow function right here. I'm going to start with the classic preventDefault on the event because we want to make sure that the button click is the only one that's going to be able to submit our form.
So what do we need to do here? Well, one thing is for sure: if someone types in a username and a password, we need to make a request to Strapi. That's absolutely given. So I'm going to say:
const response = await fetcher(...)
And I'm just going to say process.env.NEXT_..., you know this, this is the Strapi URL, and we're going to go to /auth/local. So basically we're recreating the steps that we have used using Insomnia.
And then I need to pass in a method, which is going to be the POST method. So I'm just sending in some headers as well. I'm just sending the Content-Type header to have a value of application/json. So I'm sending an HTTP POST to this URL, and I need to also send the body.
JSON.stringify, and I need to send in the identifier, which will come from data.identifier, and we need to also send the password, and that's going to be data.password, like so.
Okay. Then, once we make the request, we need to pass the request. I'm going to say responseData. You know, again, you could call this whatever you want. I'm just going to say await response... Actually, we don't need that, right? Because fetcher already returns the data. So we're just going to call that data.
And I'm just going to set a token with the data value.
Managing JWT with an auth.js Helper
So what is this setToken? Well, setToken is going to be yet another method we're going to be writing together.
And what I'll do is create a new file in the lib folder, and I'm just going to call that auth.js. And I'm going to copy a lot of code over, but we're going to go through that as well. So this particular file is going to be responsible for setting and unsetting the token. What is the token that is going to set and unset? Well, it's going to set and unset the JSON Web Token. And as you can see, I'm also using yet another dependency here. So we need to make sure that we install that real quick, which is js-cookie, that allows me to manage cookies in a very easy way. Okay, and that's pretty much done.
And so, in this auth.js file, when we set the token, we basically grab the data. And that's the data that comes back from the fetch API request. And then I say the id, the username, and the JSON Web Token should be set as part of cookies. And if the username cookie is not set... or you know, if it's set, so basically there's a username cookie available, then I just reload the page itself using the Next.js router's reload method. So that means if someone logs in and everything's correct, the username is correct, the password is correct, you know, we then set the token using the cookies. If everything is successful, we just refresh the page and then we can act on this change inside the navigation or on the page that we are at.
And likewise, we have the unsetToken where we say if someone clicks probably the logout button, which we'll implement in just a second, we want to call the unsetToken method which will remove all the cookies that we have set and it will also reload the page for us.
Okay, and this is the setToken function that we are referencing. Now there are some additional helper methods in here, which we'll come back to at a later point in time.
Finalizing the Login/Logout Flow
So in nav.js, when I say setToken, I actually need to import setToken from ../../lib/auth. And now I can essentially set the token. So theoretically, once we set the token, things will happen.
And likewise, if you look here, we have the logout link which says, on click, call the logout function. So let's actually implement that as well. It's going to be really easy.
logout is equal to this arrow function. I'm just going to call unsetToken like so, which auto-imports from that auth file. Okay, so this is, you know, this is great and it's, you know, we're getting there. But of course, if you open up the page it's still not going to work because we are missing loading, we're missing user. So where do those come from?
And I'm going to take a break here because I don't want this video to go on forever. So let's just pause here and in the next video, we're going to see where that loading and user variables come from.