A custom hook is simply a function that uses other hooks.
function useCount() {const [count, setCount] = useState(0)const increment = () => setCount(c => c + 1)return { count, increment }}
Use it like any other hook:
function Counter() {const { count, increment } = useCount()return <button onClick={increment}>{count}</button>}
Consider using a hook function inside useEffect:
useEffect(() => {const id = setInterval(increment, 1000)return () => clearInterval(id)}, [increment])
Problem: Even if increment does the same thing, its reference changes every render, causing:
useCallbackuseCallback preserves the same function reference unless dependencies change:
function useCount() {const [count, setCount] = useState(0)const increment = useCallback(() => setCount(c => c + 1), [])return { count, increment }}
Now
incrementis stable across renders.
Memoization stores results so they can be reused instead of recalculated.
const cache = {}function addOne(num) {if (!cache[num]) cache[num] = num + 1return cache[num]}
In React:
useMemo memoizes valuesuseCallback memoizes functionsuseCallback vs useMemo| Hook | Memoizes |
|---|---|
| useCallback(fn, deps) | Function |
| useMemo(() => value, deps) | Value |
Equivalent:
useCallback(fn, deps)useMemo(() => fn, deps)
useCallback stabilizes functions