DEV Community

Michael Kasdaglis
Michael Kasdaglis

Posted on

How To Have State Persist Across Refreshes

In the fast-paced world of web development, user experience is paramount. Users expect seamless interactions and a smooth flow as they navigate through web applications. One critical aspect of providing this experience is ensuring that the application's state remains intact even when the page is refreshed or closed. This is where window.localStorage comes in. In this beginner-friendly blog, we'll explore how to use window.localStorage to persist state across page refreshes.

What is window.localStorage?
window.localStorage is a built-in web browser feature that allows web applications to store key-value pairs locally within the user's browser. This data persists even after the user closes the browser or navigates away from the page. It's an excellent tool for persisting small amounts of data, such as user preferences, settings, or the current state of a web application.

Getting Started
Before diving into code examples, let's understand the basic concepts of window.localStorage:

localStorage.setItem(key, value): This method stores a key-value pair in the localStorage. Both the key and value must be strings. To store non-string data types like objects or arrays, we'll use JSON.stringify to serialize them into strings.

localStorage.getItem(key): This method retrieves the value associated with a specific key from localStorage. If the stored value is not a string, we'll use JSON.parse to deserialize it into its original data type.

Storing and Retrieving Simple Data
Let's start with a simple example where we store and retrieve a user's name:

  • Storing data
const userName = "Bird Person";
localStorage.setItem("user", userName);
Enter fullscreen mode Exit fullscreen mode
  • Retrieving data
const storedName = localStorage.getItem("user");

console.log(storedName); // Output: "Bird Person"
Enter fullscreen mode Exit fullscreen mode

In this example, we've successfully stored the user's name using localStorage.setItem and retrieved it using localStorage.getItem. The retrieved data is a string, which works well for simple values like names or preferences.

Handling Complex Data
Now, let's explore how to use JSON.stringify and JSON.parse to store and retrieve more complex data types, such as objects or arrays. Imagine we want to store and retrieve a user's settings:

  • Storing complex data
const userSettings = {
  theme: "dark",
  notifications: true,
};

localStorage.setItem("settings", JSON.stringify(userSettings));
Enter fullscreen mode Exit fullscreen mode
  • Retrieving and parsing complex data
const storedSettings = JSON.parse(localStorage.getItem("settings"));

console.log(storedSettings);
// Output: { theme: "dark", notifications: true }
Enter fullscreen mode Exit fullscreen mode

In this example, we've serialized the userSettings object into a JSON string before storing it in localStorage. When retrieving the data, we used JSON.parse to convert it back into an object. This allows us to work with complex data structures while still using localStorage.

It's essential to handle potential errors and edge cases when working with window.localStorage. Here are a few considerations:

  • Quota Exceeded: Browsers typically limit the amount of data you can store in localStorage (usually 5-10 MB). You should check for storage quota exceeded errors and handle them.

  • Data Validation: Before parsing stored data with JSON.parse, make sure it's valid JSON. Invalid JSON will result in parsing errors.

  • Key Existence: When retrieving data, check if the key exists in localStorage to avoid null or undefined values.

Let's put all these concepts into practice by building a simple to-do list application that persists tasks in localStorage.

import React, { useState, useEffect } from "react";

function ToDoList() {
  const [tasks, setTasks] = useState([]);
  const [taskInput, setTaskInput] = useState("");

  // Load tasks from localStorage on component mount
  useEffect(() => {
    const storedTasks = JSON.parse(localStorage.getItem("tasks")) || [];
    setTasks(storedTasks);
  }, []);

  // Save tasks to localStorage whenever tasks state changes
  useEffect(() => {
    localStorage.setItem("tasks", JSON.stringify(tasks));
  }, [tasks]);

  const addTask = () => {
    if (taskInput.trim() !== "") {
      setTasks([...tasks, taskInput]);
      setTaskInput("");
    }
  };

  const clearTasks = () => {
    setTasks([]);
    localStorage.removeItem("tasks");
  };

  return (
    <div>
      <h1>To-Do List</h1>
      <ul>
        {tasks.map((task, index) => (
          <li key={index}>{task}</li>
        ))}
      </ul>
      <input
        type="text"
        value={taskInput}
        onChange={(e) => setTaskInput(e.target.value)}
        placeholder="Add a task"
      />
      <button onClick={addTask}>Add Task</button>
      <button onClick={clearTasks}>Clear Tasks</button>
    </div>
  );
}

export default ToDoList;
Enter fullscreen mode Exit fullscreen mode

In this example, we've created a to-do list application that stores tasks in localStorage. Tasks are stored as an array of strings, serialized and deserialized using JSON.stringify and JSON.parse.

In this beginner's guide, we've explored the power of window.localStorage for persisting data across page refreshes. We've learned how to use setItem and getItem methods to store and retrieve data, as well as how to handle complex data types with JSON.stringify and JSON.parse. By mastering these techniques, you can enhance the user experience of your web applications, making them more user-friendly and reliable. The ability to persist user data and settings is a valuable tool in any web developer's toolkit. Happy coding!

Top comments (0)