Before React Hooks were introduced in version 16.8, sharing stateful logic between components required complex patterns like Higher-Order Components (HOCs) or Render Props. Custom Hooks completely transformed code sharing by allowing you to extract state and effects into standard, testable JavaScript functions.
Whether using built-in hooks or writing custom hooks, you must adhere to these two fundamental rules enforced by the React compiler:
This custom hook synchronizes any React state with the browser's persistent localStorage, automatically reading on mount and saving on update:
// src/hooks/useLocalStorage.js
import { useState, useEffect } from 'react';
export function useLocalStorage(key, initialValue) {
// 1. Lazy state initialization: reads from localStorage once on mount
const [value, setValue] = useState(() => {
try {
const storedItem = window.localStorage.getItem(key);
return storedItem ? JSON.parse(storedItem) : initialValue;
} catch (error) {
console.error('Error reading localStorage:', error);
return initialValue;
}
});
// 2. Synchronize to localStorage whenever 'value' changes
useEffect(() => {
try {
window.localStorage.setItem(key, JSON.stringify(value));
} catch (error) {
console.error('Error writing to localStorage:', error);
}
}, [key, value]);
return [value, setValue];
}
Notice how clean and readable your component becomes:
import React from 'react';
import { useLocalStorage } from './hooks/useLocalStorage';
function UserPreferences() {
// Acts just like useState, but persists across page refreshes!
const [theme, setTheme] = useLocalStorage('user-theme', 'light');
const [username, setUsername] = useLocalStorage('username', 'Guest');
return (
<div className={`theme-${theme}`}>
<h3>Welcome, {username}!</h3>
<button onClick={() => setTheme(theme === 'light' ? 'dark' : 'light')}>
Toggle Theme (Current: {theme})
</button>
</div>
);
}
Now let us understand how class component lifecycles map directly to modern hooks in React Component Lifecycle Methods.
Accelerate your React mastery by studying these tightly connected core tutorials:
Hook rules, dependencies, and lifecycle synchronization.
Local state preservation within reusable functions.
Displaying labels for custom hooks in React DevTools.