~2 min read • Updated Oct 22, 2025
Introduction
React’s useState and useEffect hooks are essential for managing dynamic data and side-effects. But sometimes, we want to extract complex logic into a reusable function. That’s where custom hooks come in — allowing us to encapsulate behavior and reuse it across components.
Creating the useStorageState Hook
The goal of this custom hook is to synchronize a component’s state with localStorage. It works just like useState but also reads and writes to the browser’s storage:
const useStorageState = (key, initialState) => {
const [value, setValue] = React.useState(
localStorage.getItem(key) || initialState
);
React.useEffect(() => {
localStorage.setItem(key, value);
}, [value, key]);
return [value, setValue];
};Using the Custom Hook
In your component, you can use it like this:
const [searchTerm, setSearchTerm] = useStorageState('search', 'React');This gives you a state variable and an updater function, just like useState, but with built-in persistence.
Best Practices for Custom Hooks
- Start the function name with
useto follow React’s conventions. - Return values as an array or object for flexibility.
- Make the hook generic by using abstract names like
valueinstead of domain-specific ones. - Use unique keys to avoid overwriting data in localStorage.
Benefits of Custom Hooks
- Encapsulate complex logic outside of components
- Reuse logic across multiple components
- Compose multiple hooks together
- Share as open-source utilities or internal libraries
Conclusion
Custom hooks in React are a powerful way to abstract and reuse logic. With useStorageState, we’ve created a hook that keeps state in sync with localStorage, improving user experience and code maintainability. These patterns are essential for building scalable and professional React applications.
Written & researched by Dr. Shahin Siami