Hooks and effects
Extract a small custom Hook
Move repeated stateful behavior into a named function while keeping the rendered markup in components.
A custom Hook packages reusable stateful behavior behind a clear name. The name must start with use so React knows Hook rules apply.
function useOnlineStatus() {
const [online, setOnline] = useState(navigator.onLine)
useEffect(() => {
function handleOnline() {
setOnline(true)
}
function handleOffline() {
setOnline(false)
}
window.addEventListener('online', handleOnline)
window.addEventListener('offline', handleOffline)
return () => {
window.removeEventListener('online', handleOnline)
window.removeEventListener('offline', handleOffline)
}
}, [])
return online
}
A component can now use the behavior without knowing the subscription details:
const online = useOnlineStatus()
Toggle offline mode in DevTools and the component re-renders with online set to false.
Extract a custom Hook when several components need the same synchronization or state transition logic, or when a named abstraction makes one complex component easier to read.
Keep the name specific. useOnlineStatus explains a result. useStuff hides it.
A custom Hook shares logic, not one state value. Two calls have independent Hook state, although both may subscribe to the same browser source.
Do not extract every pair of useState calls. A custom Hook should create a meaningful boundary, not move code to another file without improving the model.
Custom Hooks can return objects or arrays, just like useState. Returning [online, setOnline] would mirror built-in Hook style, but a single boolean is enough when the caller only needs to read status.
You can compose custom Hooks too. A usePersistentTasks Hook might combine useState, useEffect, and local storage logic while the UI component focuses on markup.
Testing custom Hooks often means testing a tiny component that calls the Hook, because Hooks only run inside React components or other Hooks.
Follow the same Hook rules inside custom Hooks: only call them at the top level, never inside conditions or loops.
Use the Hook from two components and toggle offline mode in DevTools. Both should update, and removing one component should clean up only its listeners.
Lesson completed