Using LocalStorage with React
Tags: javascript, redux, react
Published: 2021-06-07 15:50:41

I am working on an application that uses React and Redux and I wanted to add a login page but I didn't have time initially to create a fully secure frontend login. So, as a placeholder I used **localStorage** to keep track of who was logged in. Let me show you how I did it.

## First: Look at your REDUX Store

After someone logs into my site I add the user to my Redux Store:

```
...state
user: { id: //user's ID from the database
        username: //name the user chose to login with
        ...other_data //other data I associated with a user
       }
```

This works easily enough. As long as the state exists in the Redux store I can see who is logged in. The only issue is if someone refreshes or types a URL directly. If that happens the store has to be re-generated and the user appears to not be logged in.

## Second: Set up props on a component

So, I just had to use some lifecycle methods with **localStorage**.

I can't use **componentDidMount()** initially because when you first come to the application the user has not logged in. So when the component mounts there won't be any user data. So instead I looked to **componentDidUpdate()**.

To make this work I had to insure that I had the user.id in props. This way when the user logged in, the user.id would change and therefore the props would change. Then this component would update allowing my **componentDidUpdate()** to trigger.

```
function mapStateToProps(state) {
  return {user: {id: state.user.id}}
}
```

Note that I only retrieved the user's ID and not the entire user object from the store's state. This is because I have other data stored as an array within the user object and that data can change pretty frequently. I don't want this page to need to re-render whenever a user's data changes. I only want to re-render when the user object changes completely.

This might sound obvious, but it tripped me up for a while because I didn't consider what would trigger this page to re-render.

## Third: Use Lifecycle Methods and localStorage 

So now that I have the correct props coming in I can set up my **componentDidUpdate()** method.

```
componentDidUpdate(prevProps) {
      localStorage.setItem('userID', this.props.user.id);
    }
}
```

Pretty straight forward here. When this page re-renders it grabs the ID from the props and sets it in **localStorage**. That first argument is basically a variable name and the second is the value. I called it 'userID' but you can name it whatever you want.

What this doesn't account for is if someone logs out. I also need to clear the **localStorage** when someone logs out. I could have cleared **localStorage** in the reducer or on the page where a user chooses to log out but I wanted to have all my **localStorage** accessing in one place. So I added a little bit of logic to this **componentDidUpdate()** method.

```
componentDidUpdate(prevProps) {
    let storedID = localStorage.getItem('userID');
    if (this.props.user.id && this.props.user.id !== storedID ) {
      localStorage.setItem('userID', this.props.user.id);
    }
}
```
Now I first check **localStorage** and grab the userID that is stored there. If I am coming to the application for the first time this won't find any data. That's ok. This method shouldn't run anyway since it will only run when the user.id in props changes. If you've logged out, it will find the old userID here. (*Did you know:* the same userID should be stored in prevProps as well!)

Now for that little bit of logic. If there is now a user.id in the props and that user.id is different from the what's already in the **localStorage** set the **localStorage** with the new user.id. If you are logging out it will set this **localStorage** to a blank string.

## Finally: Let's deal with Users who Refresh the page!

One last thing to worry about, and truly the only reason I am using **localStorage**. What if someone refreshes the page or types a URL directly instead of using my easy links? (*Why is this someone not trusting the simplicity of this SPA?*)

This is where **componentDidMount()** comes into play. When this page is mounted for the first time I need to do a little checking.

```
  componentDidMount() {
    let userID = localStorage.getItem('userID');
    if (userID) {
      this.props.findUser(userID)
    }
}
```

Once again I tell my component to check **localStorage** for a userID. If a user is already logged in it will find that stored userID. So then I just call a method (that I defined earlier with an action) to use this userID to find the user data in my database. The reducer will then log that user in as if they hadn't cruelly refreshed the website.

## Was this a good idea: NO! but also Yes!

Is this a secure way to store user ID's and keep track of who's logged in. NO! 

But it's simple and can definitely be used for less critical data. And in my case it's ke[t my program running until I can come back and add the more secure log in functionality. So it's still useful.