Side Effects in React – Synchronizing State with localStorage Using useEffect

In React, a component’s output is usually determined by its props and state. But sometimes we need to interact with external systems like localStorage or APIs — these are called side-effects. This article explains how to use the useEffect hook to manage side-effects, synchronize state with localStorage, and improve user experience by persisting data across browser sessions.

useEffectside-effectlocalStoragestate synchronization

~2 min read • Updated Oct 22, 2025

Introduction


React components typically render based on props and state. But sometimes we need to interact with external systems like localStorage, APIs, or timers. These interactions are called side-effects and should be handled carefully to keep components predictable and maintainable.


Storing Search Term in localStorage


To improve user experience, we want to store the latest search term in the browser so it persists after refresh or reopening:


const handleSearch = (event) => {
  setSearchTerm(event.target.value);
  localStorage.setItem('search', event.target.value);
};

And for initializing state:


const [searchTerm, setSearchTerm] = React.useState(
  localStorage.getItem('search') || 'React'
);

The Problem with Inline Side-Effects


If we only update localStorage inside the handler, other updates to searchTerm won’t sync. The solution: use useEffect to centralize the side-effect:


React.useEffect(() => {
  localStorage.setItem('search', searchTerm);
}, [searchTerm]);

Now, every time searchTerm changes, localStorage is updated automatically.


Key Concepts of useEffect


  • First argument: the function that performs the side-effect.
  • Second argument: dependency array that determines when the effect runs.
  • Empty array: runs only once on mount.
  • No array: runs on every render.
  • Can return a cleanup function to release resources.

Advanced Tip: Use ?? Instead of ||


If the stored value is "", the || operator treats it as false and falls back to "React". To fix this, use the nullish coalescing operator ??:


const [searchTerm, setSearchTerm] = React.useState(
  localStorage.getItem('search') ?? 'React'
);

Conclusion


Using useEffect to manage side-effects makes React components more robust and predictable. By syncing state with localStorage, we preserve user data across sessions and improve the overall experience. These techniques are essential for building professional, user-friendly React applications.


Written & researched by Dr. Shahin Siami