React Learnings from 2018 - using LocalStorage
Published: 2020-11-03 10:44:34

---
title: React Learnings from 2018 - using LocalStorage
published: true
description: A series of blog posts first written in 2018. Possibly outdated.
tags: 
//cover_image: https://direct_url_to_image.jpg
---

Now (from previous posts) we have some grocery store items saving in a remote database, we can leverage localStorage to store the user's order so that it isn't just completely lost when they refresh or close the browser. This post is all about understanding LocalStorage.

Lets break it down the basic questions we will need to answer on the way:

- *What* is localStorage
- *When* to save to localStorage
- *What* to save to localStorage 
- *How* to save to localStorage
- *How* to retrieve from localStorage
- *When* to display from localStorage

I think I am going to get really tired of writing localStorage by the end of this post.

# What is localStorage?

*localStorage* or `window.localStorage` is a read-only property that provides access to a Storage object that is saved between browser sessions for that site. It is the sister of *sessionStorage* which, as the title says, exists while the page session does. As it uses object notation, it wants things as a key value pair.

This [MDN Article](https://developer.mozilla.org/en-US/docs/Web/API/Window/localStorage) explains it in more detail.

## How can we use localStorage?

Playing with localStorage is fairly simple:

We can *Add* by doing a `setItem`:

`localStorage.setItem("myName", "James")`

We can *Read* by doing `getItem`:

`localStorage.getItem("myName")`

We can Remove by doing `removeItem`:

`localStorage.removeItem("myName")`

You can remove everything with a `clear`

`localStorage.clear()`

# WHEN to use localStorage

Whenever a user changes thier order we want to send the new value to localStorage. Since React updates a component whenever we make a change to it's state, there is a lifecycle method we can use called `componentDidUpdate()`

# WHAT to save to localStorage

We can't just save just one order object as we are using a different set of orders per store so we need to include the store as the key, and the relevent order as the property. Handily, this is a param provided to us via react router:

```js
componentDidUpdate(){ 
    localStorage.setItem(this.props.match.params.storeId, this.state.order)
    }
```

## Slight gotcha here... Of Objects and Strings ##

localStorage wants the key and property to be a string, however `this.state.order` is an object so you will instead see `[Object object]` how do we fix that?

`JSON.stringify(this.state.order)`

And conversely, we need to do `JSON.parse` to bring it back as an object at a later point.

You should now have your order going into localStorage.

# Reading the localStorage on Mount

While we can get things into localStorage, when we refresh the page, the order in state is blank again. Thats because the `componentDidMount()` method, triggers an `componentDidUpdate()` to nothing. To fix this we need to reinstate localStorage as part of the component mounting:

1. First pick up the localStorage string from params: `const localStorageRef = localStorage.getItem(params.storeId);`

2. Secondly, set the state while converting it to an object `this.setState({ order: JSON.parse(localStorageRef)})`

## Asynchronous issues

Now that we have the order being read on mounting we will encounter an issue.

localStorage is now carrying an order which refers to groceries which, in our previous post, is coming from Firebase. since Firebase is cloud-hosted, it will never be ready before the data from localStorage needs it. It will say something like `cannot read Status of undefined`

**How do we fix that?**

The update that contains the information from Firebase only takes a moment to arrive so here it is a case of holding off working on the values till it has loaded. The offending line is in the Order Component:

`const isAvailiable = grocery.status === "availiable";`

We can change that to:

`const isAvailiable = grocery && grocery.status === "availiable"`

However, for the split second it takes for the data to arrive, the order will display the messae saying the item is unavailible which is messy, so a smarter way is to simply say:

`if(!grocery) return null`

This wont render anything till we have the database of groceries ready to go.

## Conclusion

Using localStorage is a fairly straightforward process, there is just a few gotchas you need to be aware of. The worse of which is the timing ascpect around accessing the database. A good understanding of lifecycle methods in React helps with this...perhaps thats a post for another time.