Many React Hooks — like useEffect, useMemo, and useCallback — accept a dependency array as their second argument. This array controls when the hook runs by listing all the values that the hook depends on.
If you understand dependency arrays well, you can avoid unnecessary re-renders, stale data, and performance issues in your React apps.
✅ Core idea: “Run this hook only when these values change.”
The dependency array tells React: “Run this hook’s function only when one of these values changes.”
// Effect runs only when 'count' changes
useEffect(() => {
console.log("Effect runs when count changes");
}, [count]);
In this example, the effect re-runs only when count changes — not on every render.
useEffect, useMemo, and useCallback.General pattern for hooks with dependency arrays:
// Generic pattern for a hook with dependencies
useEffect(() => {
// side effect logic that uses a, b, c
}, [a, b, c]);
You must list every value that is used inside the hook’s callback and can change over time: props, state, memoized values, or functions.
// Effect depends only on 'count'
function Counter() {
const [count, setCount] = React.useState(0);
const [name, setName] = React.useState("");
React.useEffect(() => {
console.log("Effect triggered because 'count' changed");
}, [count]);
return (
<div className="text-center">
<input
className="form-control w-50 mx-auto mb-2"
placeholder="Enter name"
value={name}
onChange={(e) => setName(e.target.value)}
/>
<p>Count: {count}</p>
<button
className="btn btn-primary"
onClick={() => setCount(count + 1)}
>
Increment
</button>
</div>
);
}
count and does trigger the effect.count changes.Conclusion: The effect depends only on count, not on name.
// Effect runs only once after initial mount
useEffect(() => {
console.log("Runs only once after mount");
}, []);
An empty dependency array means the hook runs only once on mount, similar to componentDidMount. Use this for one-time setup, like initial API calls or event listeners (with proper cleanup).
// Effect re-runs when 'count' or 'name' changes
useEffect(() => {
console.log("Effect depends on count and name");
}, [count, name]);
The effect runs whenever any one of the listed dependencies changes. If either count or name updates, the effect will run again.
| Hook | Purpose of Dependency Array |
|---|---|
useEffect |
Controls when side effects re-run |
useMemo |
Controls when computed values are recalculated |
useCallback |
Controls when memoized functions are recreated |
// useCallback keeps 'log' stable between renders
function Example() {
const [count, setCount] = React.useState(0);
const log = React.useCallback(() => {
console.log("Count is", count);
}, [count]);
React.useEffect(() => {
log();
}, [log]);
}
Wrapping log() inside useCallback prevents unnecessary effect re-runs by stabilizing its function reference, while still updating whenever count changes.
useCallback or useMemo to stabilize dependencies that are functions or objects.[] — but ensure the logic is safe.react-hooks/exhaustive-deps rule to automatically warn about missing dependencies.useRef for values that do not need to trigger re-renders when they change.useEffect that logs whenever state changes — then try adding/removing dependencies.useMemo calculation that depends on two values and see how it behaves when one changes.useCallback to stabilize function dependencies.Goal: Master dependency arrays so that React Hooks run efficiently, correctly, and only when their true dependencies change.