useEffect Dependency Array
The magic of `useEffect` lies in its second argument: the **dependency array**. This array tells React when to re-run your effect. Understanding it is crucial for writing efficient and bug-free React applications.
What is the Dependency Array?
The dependency array is an optional second argument to `useEffect`. It lists all values from the component scope (props, state, variables) that the effect depends on. React will re-run the effect only if any of these values have changed between renders.
The dependency array is how you tell React: "Hey, only re-run this effect when these specific things change."
Three Scenarios of Dependency Array
Scenario 1: No Dependency Array
useEffect(() => { console.log('This runs after EVERY render!');}); <!-- No array -->This effect runs after every single render. This is rarely what you want because it can cause performance issues or infinite loops if you update state inside it.
Scenario 2: Empty Dependency Array []
useEffect(() => { console.log('This runs only ONCE after the first render!');}, []); <!-- Empty array -->This effect runs only once, right after the component mounts. It's perfect for:
- Fetching initial data from an API
- Setting up subscriptions that should only happen once
- Logging page views
Scenario 3: Dependency Array with Values [a, b]
useEffect(() => { console.log('This runs when count or name changes!');}, [count, name]); <!-- Array with dependencies -->This effect runs on the first render (mount) and then again whenever `count` or `name` changes between renders.
Common Mistakes with Dependency Array
Mistake 1: Missing Dependencies
function Counter() { const [count, setCount] = useState(0);
<!-- BUG: Missing 'count' in dependencies --> useEffect(() => { console.log('Count is', count); }, []); <!-- This will always show count as 0! -->}Mistake 2: Including Unnecessary Dependencies
function Timer({ initialSeconds }) { useEffect(() => { const interval = setInterval(() => { console.log('tick'); }, 1000); return () => clearInterval(interval); }, [initialSeconds]); <!-- 'initialSeconds' is not used inside effect! -->}This causes the timer to reset whenever `initialSeconds` changes, even though it's not used. The effect doesn't need it.
The React Hooks ESLint Plugin
React provides an ESLint plugin called `eslint-plugin-react-hooks` that helps catch dependency mistakes. It has a rule `exhaustive-deps` that warns you if your dependencies are incorrect.
If you see an ESLint warning about missing dependencies, don't just ignore it or disable the rule. Fix it by adding the missing dependency or refactoring your code.
Example: Correct Dependency Usage
function SearchResults({ query }) { const [results, setResults] = useState([]);
useEffect(() => { let isCurrent = true; <!-- Flag to prevent setting state after unmount --> fetch(`https://api.example.com/search?q=${query}`) .then(response => response.json()) .then(data => { if (isCurrent) { setResults(data); } }); return () => { isCurrent = false; <!-- Cleanup flag --> }; }, [query]); <!-- Correct: re-fetch when query changes -->
return <!-- render results -->;}Two Minute Drill
- The dependency array controls when a `useEffect` hook re-runs.
- No array → runs after every render.
- Empty array `[]` → runs only once on mount.
- Array with values `[a, b]` → runs on mount and when a or b changes.
- Always include all values from the component scope that the effect uses.
- Don't include values that the effect doesn't use.
- Use the `exhaustive-deps` ESLint rule to catch dependency mistakes.
Need more clarification?
Drop us an email at career@quipoinfotech.com
