Django Rest Framework with React : JWT Authentication part 2

Aha! So there’s more to this saga.

Keshav Vinayak Jha
Techspace
8 min readSep 10, 2019

--

https://www.codingforentrepreneurs.com/

INTRODUCTION

This blog is the second part of my series of blogs written upon integration of DRF and React. To understand the context of this blog, I’d highly recommend reading my previous blog. In this continuation, we are moving on to the client side rendering of our application. If you so wish, you can grab the completed code from here.

Since our focus isn’t on creating a beautiful UI, I hope you don’t throw up after seeing the finished website, rather appreciate the internal working of the web app. With expectations lowered, let’s begin !

So far, we have set up two main APIs, one for registering a new user, and another for logging in with the user details. We set up the jwt settings such that we receive both user information and the token with a call to a singular API. This was done so that we can store our user’s information in some state that we can pass down (Or use context) to the end component that utilizes it.

I’ll avoid using Redux for the sake of simplicity and in the hopes of teaching custom form validation. You should always initialize projects with the bare basics and your current knowledge and not bring in more complexity until required. That being said, Redux is a great tool and in the hands of an experienced developer is a huge time saver and code optimizer.

PROJECT STRUCTURE

Dive within your root directory and initialize the react application. I’m using npm version 6.11.1, which includes npx beforehand, and react version 16.9.0. Check your version and update accordingly.

cd simple_rest
npx create-react-app frontend

The front-end app will consist of a NavBar, login and registration component, and will include a simple display of user information when logged in. Simple stuff. cd into the frontend directory and create a Components folder inside src/ . Within Components, create NavComponent, and Acconts/LoginUser, Accounts/RegisterUser

cd frontend/src
mkdir Components
cd Components
mkdir Accounts
touch NavComponent.js
touch Accounts/LoginUser.js Accounts/RegisterUser.js

Open up your editor to the project directory and let’s begin working on the components !

within public/ create a file config.js, which will hold reusable information that we don’t want to hard code everytime. We’ll create a variable to hold our server address value, 127.0.0.1:8000, which points to the django server.

var SERVER_ADDRESS = "http://127.0.0.1:8000/";

We can import all variables from this file as window.<variable_name> since all loaded javascript objects become part of the window object. In the head part of public/index.html, add the following to make it a part of the window variable

<script src=”%PUBLIC_URL%/config.js” type=”text/javascript”></script>

Oof, now we can finally move on to define our components.

DEFINING THE COMPONENTS

Let’s take a top down approach and start with the App component. As discussed, the app component will be responsible for handling login, form display, and user information display if authenticated. We can very well include a function for handling registration within the app itself but I want to explain registration separately. Following is the complete App component, let me explain line by line what I did.

Assuming the NavComponent created, we import it just like that. The App component has three states, logged_in, username, and displayed_form. The logged_in state tells us if the user is authenticated via fetching the jwt token from the localStorage. We store the token in the localStorage after doing a successful login. The username is the disscussed user information, and the displayed form handles the currently displayed form, by passing it down to the NavComponent.

The componentDidMount() Lifecycle method is executed before the render() method, and fetches user information (username in this case) if there is a token. The token is removed when logged out, the handleLogout method makes sure of that. The display_form method is used to set the displayed_form, which proceeds to display the form in arguement. The handleLogin makes a POST request to the token-auth/ endpoint, which returns the user information along with the JWT, and then proceeds to set the username state.

Finally, we break down the state into its constituents to pass down as props to the NavComponent, along with all the define methods. Below the NavComponent, we check if the user is logged_in, and display the appropriate text. With this, we’re done with the App component, let’s move onto the NavComponent.

Within the render() method of the component, we first retrieve the form we require by checking the value of the displayed_form (state of the app component passed down as a prop), accordingly we select either the LoginComponent or the RegisterComponent, which are just the forms for performing either of the two operations. The NavBar while logged in and logged out are different, accordingly, we define both of them, Calling the disply_form() method for the logged_in form ( Nav to display when logged_out) and calling the handleLogout on click of the button defined within the logged_out_nav (Nav to display when logged_in).

Within the return method, we simply check if logged_in state of the app is true or not, and accordingly render the corresponding nav. Also, we can simply place our form within curly braces, which will be empty if none is selected.

So far so good ! Let’s move on to defining the LoginUser component.

This post was made by back-end developers gang

Oh right, before proceeding to copy this file, remember to install ‘reactstrap’, the reactified version of bootstrap, we’ll be using the imported Styled Component Row to give this crappy UI some sense.

npm install reactstrap

Alright, just one arrow function to define here, the handlePassswordChange method to set the password state when there is a change in the input component.

Moving on to the render() method, We start defining our Form, We had passed down the handleLogin method from the App component(Remember?), so we just pass the username and the password to this method when the form is submitted.

Within the input for the username, when a change in input is detected, we call the handleLoginChange method (Passed from the App component), and the value corresponds to the state username of the App component as well.

In the input for the password, we set the value as the state password within this component itself, as we do not need it elsewhere. Then there’s the submit button, and that’s it ! LoginUser is done.

Time to dive into the deep mess that is custom validation for user registration. Stay strong.

Bad design, bad me. Boo

Oh, did I mention I’d be using Axios for my API call here? No? Okay, there you have it.

npm install axios

Let’s start from the top, I’ve created 4 es6 functions that will act as my validators, the first one checks for the existence of the specified field (required), the second checks if the length of the value is greater than specified, and that it exists (minLength), vice versa is maxLength is, and isEqual returns true if the two values are equal.

Okay so the state properties are as expected, the values that the form will take, first name, last name, username, password, password2, oh and what’s that? the display_<property> property defines when the errors are supposed to display (To avoid infinite calls to setState). This will become clearer when we observe the code below.

The getErrors function simply returns all validation the errors(if any) is currently occurring in the specified input field. The isValid prevents the form from submission in case any error is observed in any input field. At the end of the getErrors function, notice how I have commented out the setState function for the highly not recommended direct mutable call for setting state. This is mainly done to avoid React from getting into an infinite cycle of setting states, as the getErrors function is called as is in the render() function. Try uncommenting the code and watching the errors.

The clear form function clearly clears the form (Ok sorry). The sendRegistration function handles the submission of form. It checks for invalid input, if not any, makes a POST request to the users/create endpoint and subsequently clears the form.

The changeHandler function here does two things ; One, set the state of the corresponding input field as soon as a change occurs. Two, grabs the name of the input field, and sets the display_<input_field_name> to true, so, we can now see any invalidation in the corresponding field.

Great ! We’re done with all our helper functions, Now we just need to put together all the pieces and form a form.

The first thing you’ll notice is that I’ve added a noValidate property to my form component. Why? Because we’re interfering with the validation process and doing it on our own terms, so we do not require React to deal with its internal checks. Next, the input fields are as expected. I’ve added a render for all the errors that may occur for the corresponding inputField.

This was an extremely hard-coded form and it might take some time to soak in all the bits. Fortunately, you do not have to ever use something like this, you’ll mostly be using react-redux-form for replacing much of this code.

Okay ! Let’s test out our app now. Go into the front-end directory and run

npm start

Subsequently, go into the root simple_rest directory and run

python manage.py runserver

So, we got both our django server and react app running, let’s test it out.

Front-end engineers, save yourself the eye bleeding.

Click on the signup thingy, and try registering a new user

Testing out the form validation.

After registering a new user, click on the Login text to load the form.

Funny guy

Click on the Login button and voila!

Yay

I highly recommend opening up the Network tab in the dev tools and checking out various requests made, or watching the console tab for the various logging I’ve placed in my code for watching states or response objects.

WHAT’S NEXT

In this 2 part series, We created a small app based around JWT Authentication by using Django Rest Framework and React on the frontend. I’ve placed the link for the project in this post, but you’ll see that there are various models and functions in that repository that are not in context with these articles, that’s because I’m working on a bigger project of which this authentication was a part of. Moving Forwards, I’ll be posting many more blogs related to Django, Python, React, JavaScript, Development and much more. Stay tuned !

--

--