Learning React Even on a “Busy Holiday” – Saving Data to Local Storage with useEffect

Published: (January 5, 2026 at 03:50 AM EST)
2 min read
Source: Dev.to

Source: Dev.to

Why Use localStorage with React?

When you first start with React, many examples feel temporary: you refresh the page and everything disappears. Real applications, however, need to persist data such as:

  • User preferences
  • Theme settings
  • Watched movies
  • Cart items
  • Form drafts

localStorage allows the browser to store data persistently, even after a page reload or browser restart.

State vs. localStorage

  • React state lives in memory (temporary).
  • localStorage lives in the browser (persistent).

The goal isn’t to replace state but to sync state with localStorage. By reading from localStorage first, you can avoid hard‑coding default values.

Initializing State from localStorage

Using a state callback function ensures the read happens only once, during the initial render:

import { useState } from "react";

const [items, setItems] = useState(() => {
  const stored = localStorage.getItem("items");
  return stored ? JSON.parse(stored) : [];
});

Why this matters

  • The function runs only once, preventing unnecessary reads on every render.
  • The app loads with saved data automatically.

Keeping localStorage in Sync with useEffect

Whenever the state changes, we want to update localStorage. useEffect runs after render, and the dependency array guarantees it runs only when the specified state changes.

import { useEffect } from "react";

useEffect(() => {
  localStorage.setItem("items", JSON.stringify(items));
}, [items]);

Key points

  • useEffect runs after the component has rendered.
  • The dependency array ([items]) ensures the effect runs only when items changes.
  • This keeps browser storage always up‑to‑date.

Handling Data Types

localStorage stores only strings. Therefore:

  • Objects → JSON.stringify(obj)
  • Arrays → JSON.stringify(arr)
  • Reading back → JSON.parse(storedString)

Forgetting to stringify/parse leads to subtle bugs.

Takeaways

  • Persisting data with localStorage is a small but essential habit for real‑world React development.
  • Use a state initializer callback to read from localStorage once.
  • Sync state back to localStorage with a useEffect that depends on the state.
  • Always stringify before storing and parse after retrieving.

By incorporating these patterns, you ensure your React apps survive real user actions and page reloads, keeping momentum even on busy days.

Back to Blog

Related posts

Read more »

React Coding Challenge : Card Flip Game

React Card Flip Game – Code tsx import './styles.css'; import React, { useState, useEffect } from 'react'; const values = 1, 2, 3, 4, 5; type Card = { id: numb...