ReactJS with DRF: How to Authenticate users with a Token in the LocalStorage!
I am building an application with reactJS in front-end and DRF(Django-Restful-Framework) in back-end . As always, I encountered with a number of challenges, solved them, and move forward . Below is one of them.
The Challenge:
When a user tries to login, I want my application to be able to recognize auth-token in the user’s local storage in the web browser. That is, if the user has the auth-token in the local storage, my application should log him in automatically without requiring him to even click login button.
Assumptions:
The user has already signed up in my back-end DRF capable of issueing auth-token. The user may or may not have the auth-token because he uses many different computers or browsers.
At first, I thought one of the lifecycle method, “componentWillmount”, would solve the problem because it is the method called right before rendering a component. But it did not. I realized states changed by “componentWillmount” are not reflected in the rendering.
*For your information, the “componentWIllmount” method will be soon deprecated in React 17 due to its unsafeness so it is better not use it anyway.
To do this, I had to set “initial states” right after a component class is created, not right before the component is rendered. Like other programming languages, “constructor” is the first method to be called after a react component class is created. Thus, setting initial states inside constructor solved the problem. The code below is how I set the state in constructor.
class Working extends Component {
constructor(props){
super(props);
console.log("constructor started.");
let auth_token = this.handleCheckTokenExist();
this.state = {
home:{username:"",password:"",auth_token:auth_token}
};
} handleCheckTokenExist = () => {
if(localStorage.getItem("auth_token") !== null){
return true;
}else{
return false;
}
}; render() {
return (
<div>
........
</div>
);
}
As a result of testing, unlike componentWillmount, the initial states set by constructor is well reflected in rendering.
I usually set states directly in class outside constructor like “state={key:value …}” and modify states with “this.setState” like the code below since it gives a better readability and consiceness in the code. However, if I want to adjust the initial states subject to varing with somthing, which is an exisistence of auth-token in my case, the states have to be set inside constructor.
*For your information again, in case you modify the state set inside constructor, you better use arrow function like I did to handleCheckTokenExist() than traditional javascript function to avoid forceful binding with constructor.
class NotWorking extends Component {state = {
home:
{username:"",password:"",auth_token:auth_token}
}handleCheckTokenExist = () => {
if(localStorage.getItem("auth_token") !== null){
this.setState({ .....})
}else{
this.setState({ .....})
}
};render() {
return (
<div>
........
</div>
);
}
Thank you for reading. I hope this save you some searching time. Please let me know if there is any questions, concerns, or better way to get this done.