Custom hooks
🏠The everyday picture
A standard operating procedure written once, "how we open the shop each morning", that any branch can follow instead of each inventing its own.
📘What it really is
- A custom hook is a function whose name starts with
use, which calls other hooks, so stateful logic can be shared between components:
export function useLocalStorage<T>(key: string, initial: T) {
const [value, setValue] = useState<T>(() => {
try {
const saved = localStorage.getItem(key);
return saved ? (JSON.parse(saved) as T) : initial;
} catch {
return initial;
}
});
useEffect(() => {
localStorage.setItem(key, JSON.stringify(value));
}, [key, value]);
return [value, setValue] as const;
}
- Use it like
useState:const [enquiries, setEnquiries] = useLocalStorage("enquiries", sampleEnquiries);. - Each component using a custom hook gets its own state; hooks share logic, not data.
- Custom hooks keep components short and readable, and can be tested separately.
-
Common examples:
useLocalStorage,useDebounce(wait until typing pauses),useMediaQuery,useFetch(Module 38 shows a better approach for fetching). -
Note the
as There trusts that stored data has the right shape. For anything important, check it properly (Module 30, Lesson 4).
🖱️Try it
Create src/hooks/useLocalStorage.ts as above and replace your Lesson 1 loading and saving code with it. Then write
useDebounce(value, delay) that returns the value only after it stops changing for delay milliseconds, and use it
so the search filters 300ms after typing stops.
✅Quick check
Why must a custom hook's name start with use?
Show the answer
It tells React (and its lint rules) that it's a hook, so the rules of hooks are checked inside it.
Two components use useLocalStorage with different keys. Do they share state?
Show the answer
No. Each call has its own state; only the logic is shared.
