Web optimisation through caching with local storage in React applications.

Web optimisation through caching with local storage in React applications.

Enhance your website/web application’s speed by storing frequently requested data in the local storage.

·

6 min read

Introduction

As front-end developers, an unsaid rule when implementing functionalities is to ensure that we implement it in such a way that wouldn’t affect the web performance or better still, improve it.

Sending requests to servers to get data for users and, probably display this data as required, to the user could sometimes affect the loading speed. This could be because of the slow network from the server side or the client side and could in turn reduce user experience. We could solve this problem through a concept called caching. In this article, we are going to take a deep dive into what caching is all about and how to go about it with the local storage.

What is caching?

Caching is simply storing data from previous requests from the server in a location closer to the client to enhance loading time. Simply put, it is the storing of frequently requested data/content closer to those asking for it. For example, if we have a request hitting a particular API to get some data to be displayed for users, every time our website/app loads, a new request is sent to the API to retrieve this data and this could take time which in some scenarios might affect the performance of the site. Storing this data in a location closer to your users will be a way to solve this issue. Luckily, the browser provides a simple way to cache data in the local storage of the browser and that is what we will be covering in this article. Let’s dive in.

Caching data with local storage.

Before we fetch the data to be cached, let's quickly see how the local storage in the browser works.

localStorage.setItem(key, data);//This method Stores the data in the local storage. The key serves as an identification or the name of the data localStorage.getItem(key); 


localStorage.getItem(key); //This method returns the data associated with that key

Local storage has several methods but the two we will be looking at in this article are the setItem and the getItem method.

The setItem method stores data in the local storage of the browser in a key-value pair. That is, it takes in the key which must be anything unique and serves as a form of identification of the data that is meant to be stored and the value which is the data itself that is to be stored, this value is meant to be in a string form.

The getItem method is used to retrieve the data when needed. Now that we understand how the localStorage works, let’s go ahead to set up our project and fetch our data from the Tony Hawk API and display it for the users.

function App() {
 const [skaters, setSkaters] = React.useState([]);


 const fetchData = async () => {
   const url = "https://thps.now.sh/api/skaters";
   const response = await fetch(url);
   const data = await data.json();
   setSkaters(data);
 };


 useEffect(() => {
   fetchData();
 }, []);


 return (
   <div className="App">
     {skaters.map((person) => {
       return (
         <p key={person.name}>
           {person.name}: {person.style}
         </p>
       );
     })}
   </div>
 );
}

Run this code

What we did up there, was to create a file called App and then fetch our data from the API endpoint provided above which returns a list of skaters in a particular region. After which, I displayed the data that was gotten from the API, that is, a list of all the skaters' names and their skating styles.

Every time this page is reloaded for one reason or the other, it may take a little more than a second to load and this is simply because, for every reload, there is a trip to and fro from the server to the client to get the data and display it, this is what happens behind the scene anything we fetch request for any data.

To combat this, we can cache data into the browser's local storage immediately after the first request from the server and render it when needed instead of making a round trip to the server and back each time an API call is made like in the example below:

function App() {const [skaters, setSkaters] = useState([]);
 const fetchData = async () => {
   const url = "https://thps.now.sh/api/skaters";
   const response = await fetch(url);
   const data = await response.json();
   // Set the fetched data into the local storage
   localStorage.setItem(url, JSON.stringify(data));
   // Check if there is actually any data in the localstorage conditionally to avoid any future bugs
   const cachedData = JSON.parse(localStorage.getItem(url)) || null;
   if (cachedData) {
     setSkaters(cachedData);
   }                
 };
 useEffect(() => {
   fetchData();
 }, []);
 return (
   <div className="App">
     {skaters.map((person) => {
       return (
         <p key={person.name}>
           {person.name}: {person.style}
         </p>
       );
     })}
   </div>
);
}

This does the trick. Referencing the code above, I added 3 lines of code to our previous code block to get our desired result. I stored the data that we fetched from the skaters API into our localStorage with the setItems method, we earlier discussed that the localStorage only accepts strings, so we then change the data gotten into a string format with the JSON.stringify, and we then have the data stored in the local storage. Now that we have it stored in our browser, we then retrieved it and change it back to a javascript object with JSON.parse and went on ahead to use the || syntax checks if the data we stored in the local storage is actually there( this is just a step to prevent any bugs in the future) and then displays it.

If you run this code in your browser, you would notice how fast our data is being rendered. While this is very good for a fast and responsive website, this can pose a problem on the client side if the data cached in the local storage has been updated on the server .That wouldn’t look too good for our web applications. A way to approach this would be to display our cached data and still request for fresh data from the server and when the fresh data is finally available from the server, the UI is automatically updated with it.

This is illustrated in the code below.

function App() {
 const [skaters, setSkaters] = useState([]);
 const fetchData = async () => {
   const url = "https://thps.now.sh/api/skaters";
   // We Display the cached data while awaiting the response from the API call
   const cachedData = JSON.parse(localStorage.getItem(url)) || null;
   if (cachedData) {
     setSkaters(cachedData);
   }
   const response = await fetch(url);
   const data = await response.json();
   localStorage.setItem(url, JSON.stringify(data));
// After the we get our data from the server, this fresh data from the server is rendered immediately
   setSkaters(data);
 };


 useEffect(() => {
   fetchData();
 }, []);


 return (
   <div className="App">
     {skaters.map((person) => {
       return (
         <p key={person.name}>
            {person.name}: {person.style}
         </p>
       );
     })}
   </div>
 );
}

In the code above, the cached data is obtained first, then rendered while the API call is happening asynchronously behind the scene.

This means, we save our frequently requested data in the local storage after initial loading, so for every other loading of that particular page, the cached data is displayed first and then the fresh data automatically replaces the cached data once it is available from the API call. This means your users see the cached version of data immediately and receive the updated version when the API responds. This helps us to solve the issue of updated data in the server while still maintaining the good performance of the website.

Conclusion

As we build web applications, the performance and optimization of our apps should be prioritised for a better experience for our users. There are various things to put in place for this to happen and caching data that is frequently visited and also doesn’t change easily could help in boosting performance if used in the right way. So this optimisation technique should be considered when building certain types of websites or applications.