A custom hook is just a function whose name starts with use and that contains reusable React logic.
The main idea is to extract logic that is shared across components so we do not duplicate the same state and effects in multiple places.
Custom hooks can be used:
- directly inside a component
- inside another custom hook
As long as the hook follows the Rules of Hooks, it works the same way as built-in hooks.
1) Why custom hooks are useful
If several components need the same behavior, we can move that behavior into a custom hook.
Examples:
- fetching data
- managing a form
- handling local storage
- tracking window size
- timer logic
This makes the component code cleaner and more reusable.
2) State inside a custom hook
A custom hook often uses useState, useEffect, or other hooks internally.
The important fact is:
- state created inside a custom hook is still part of the calling component's React state lifecycle
- updating that state causes the component to re-render, just like normal state in a component
import { useState } from 'react';
function useCounter(initialValue = 0) {
const [count, setCount] = useState(initialValue);
const increment = () => setCount((prev) => prev + 1);
const decrement = () => setCount((prev) => prev - 1);
const reset = () => setCount(initialValue);
return { count, increment, decrement, reset };
}
export default function App() {
const { count, increment, decrement, reset } = useCounter(0);
return (
<>
<p>Count: {count}</p>
<button onClick={increment}>+</button>
<button onClick={decrement}>-</button>
<button onClick={reset}>Reset</button>
</>
);
}
This hook encapsulates the counter logic in one place and can be reused anywhere.
3) Returning state and setter functions
A custom hook usually returns values that the component can use.
For example, a hook can return:
- state value
- setter function
- computed values
- helper functions
import { useState } from 'react';
function useToggle(initialValue = false) {
const [value, setValue] = useState(initialValue);
const toggle = () => setValue((prev) => !prev);
const open = () => setValue(true);
const close = () => setValue(false);
return { value, toggle, open, close };
}
export default function App() {
const { value, toggle, open, close } = useToggle(false);
return (
<>
<p>{value ? 'Open' : 'Closed'}</p>
<button onClick={toggle}>Toggle</button>
<button onClick={open}>Open</button>
<button onClick={close}>Close</button>
</>
);
}
The set function can be used outside the custom hook, and when it updates the state, the component re-renders normally.
4) Important rule
A custom hook must itself follow the Rules of Hooks.
That means it can call hooks, but it must be used at the top level of a component or another custom hook, not inside a conditional or loop.
5) Summary
- custom hooks are reusable pieces of React logic
- they are useful for extracting repeated state/effect logic
- they can call hooks like
useStateanduseEffect - state inside a custom hook behaves like normal component state
- return the values the component needs, such as state and update functions
This is one of the core patterns for writing cleaner React code: move repeatable logic into a hook, then use it in multiple components.
Top comments (0)