React Custom Hooks
Extract reusable stateful logic into your own composable hooks
Overview
A custom hook is a JavaScript function whose name starts with use and that calls other hooks. It lets you extract component logic—subscriptions, data fetching, timers—into reusable functions. Custom hooks share stateful logic, not state itself: each call gets its own isolated state.
Syntax / Usage
Compose built-in hooks inside a function that returns whatever the caller needs (values, setters, or handlers).
import { useState, useEffect } from 'react'
function useFetch(url) {
const [data, setData] = useState(null)
const [error, setError] = useState(null)
const [loading, setLoading] = useState(true)
useEffect(() => {
let active = true
setLoading(true)
fetch(url)
.then((res) => res.json())
.then((json) => active && setData(json))
.catch((err) => active && setError(err))
.finally(() => active && setLoading(false))
return () => {
active = false
}
}, [url])
return { data, error, loading }
}
Examples
Persist state to localStorage with a hook that mirrors the useState signature:
function useLocalStorage(key, initial) {
const [value, setValue] = useState(() => {
const stored = localStorage.getItem(key)
return stored ? JSON.parse(stored) : initial
})
useEffect(() => {
localStorage.setItem(key, JSON.stringify(value))
}, [key, value])
return [value, setValue]
}
Track a media query for responsive rendering:
function useMediaQuery(query) {
const [matches, setMatches] = useState(() => matchMedia(query).matches)
useEffect(() => {
const mql = matchMedia(query)
const onChange = (e) => setMatches(e.matches)
mql.addEventListener('change', onChange)
return () => mql.removeEventListener('change', onChange)
}, [query])
return matches
}
Common Mistakes
- Not prefixing the function with
use, which breaks the Rules of Hooks lint checks - Calling hooks conditionally or inside loops within the custom hook
- Expecting two components to share the same state—each call is independent
- Forgetting cleanup in effects, causing memory leaks or stale updates
- Returning unstable object/function references that trigger extra re-renders downstream
See Also
use-state use-effect react-context-patterns