0
0
Reactframework~15 mins

Dependency array usage in React - Deep Dive

Choose your learning style9 modes available
Overview - Dependency array usage
What is it?
In React, the dependency array is a list of values that tells hooks like useEffect when to run their code. It helps React know if something important has changed so it can update or run side effects only when needed. Without it, React might run code too often or not when it should. This keeps apps fast and predictable.
Why it matters
Without the dependency array, React hooks like useEffect would run their code every time the component renders, causing slowdowns and bugs. It would be like checking your mailbox every second instead of only when the mail arrives. The dependency array solves this by making React watch only the things that matter, saving time and avoiding mistakes.
Where it fits
Before learning dependency arrays, you should understand React functional components and hooks basics, especially useEffect. After mastering dependency arrays, you can learn advanced hooks patterns, custom hooks, and performance optimization in React.
Mental Model
Core Idea
The dependency array tells React exactly which values to watch so it runs hook code only when those values change.
Think of it like...
It's like a grocery list that tells you which items to buy; you only go shopping when something on the list runs out or changes, not every day.
useEffect Hook
┌─────────────────────────────┐
│ useEffect(() => {            │
│   // side effect code        │
│ }, [dep1, dep2, ...]);       │
└─────────────┬───────────────┘
              │
              ▼
  React watches dep1, dep2...
  ┌─────────────────────────┐
  │ If any dep changes → run │
  │ else → skip running      │
  └─────────────────────────┘
Build-Up - 7 Steps
1
FoundationWhat is a dependency array
🤔
Concept: Introduces the dependency array as a list of values that hooks watch to decide when to run.
In React, hooks like useEffect take two arguments: a function and a dependency array. The dependency array is a list of variables or values. React looks at this list and only runs the function if one of these values changes since the last render.
Result
React runs the hook function only when something in the dependency array changes.
Understanding that the dependency array controls when React runs side effects is the foundation for efficient React apps.
2
FoundationWhy dependency arrays prevent extra runs
🤔
Concept: Explains how React uses the dependency array to avoid running effects unnecessarily.
Without a dependency array, useEffect runs after every render. This can slow down apps and cause bugs. By listing dependencies, React compares current and previous values. If none changed, React skips running the effect.
Result
Effects run only when needed, improving performance and correctness.
Knowing that React compares dependencies helps you write effects that run only when truly necessary.
3
IntermediateEmpty dependency array means run once
🤔Before reading on: Do you think an empty dependency array runs the effect every render or only once? Commit to your answer.
Concept: Shows that an empty array tells React to run the effect only once after the first render.
If you pass an empty array [], React runs the effect only once when the component mounts. It never runs again because there are no dependencies to watch for changes.
Result
Effect runs once, like componentDidMount in class components.
Understanding this helps you run setup code only once, avoiding repeated work.
4
IntermediateCommon mistake: missing dependencies
🤔Before reading on: What happens if you forget to include a variable your effect uses in the dependency array? Commit to your answer.
Concept: Explains why all variables used inside the effect should be listed as dependencies.
If you use a variable inside useEffect but don't list it in the dependency array, React won't watch it. This can cause your effect to use outdated values or miss updates, leading to bugs.
Result
Effect may run with stale data or not run when it should.
Knowing to include all used variables prevents subtle bugs and keeps effects in sync with state.
5
IntermediateHow to handle functions in dependencies
🤔Before reading on: Should you include functions in the dependency array? Why or why not? Commit to your answer.
Concept: Discusses that functions are objects and often change identity, causing effects to run more than expected.
Functions defined inside components change on every render, so including them in dependencies causes effects to run every time. To avoid this, use useCallback to memoize functions or move them outside the component.
Result
Effects run only when truly needed, avoiding infinite loops.
Understanding function identity helps prevent common infinite effect loops.
6
AdvancedUsing custom hooks with dependencies
🤔Before reading on: How do dependency arrays behave inside custom hooks? Commit to your answer.
Concept: Shows that custom hooks also use dependency arrays and how they pass dependencies through.
Custom hooks can use useEffect and accept dependencies as parameters. The dependency array inside the custom hook should include these parameters to keep effects in sync. This pattern helps reuse logic safely.
Result
Custom hooks run effects correctly based on passed dependencies.
Knowing this enables building reusable, predictable hooks that respect dependencies.
7
ExpertWhy exhaustive-deps lint rule matters
🤔Before reading on: Does the React lint rule for exhaustive dependencies always help or can it cause confusion? Commit to your answer.
Concept: Explains the lint rule that enforces listing all dependencies and its tradeoffs.
React's eslint plugin warns if dependencies are missing. This helps catch bugs but sometimes suggests adding values that cause unwanted reruns. Experts learn to balance following the rule and using techniques like useCallback or useRef to manage dependencies.
Result
More reliable effects with fewer bugs, but requires understanding tradeoffs.
Understanding the lint rule's purpose and limits helps write robust, maintainable React code.
Under the Hood
React keeps track of the previous values of each dependency after every render. When a component renders, React compares the current dependency values with the previous ones using Object.is comparison. If any value changed, React schedules the effect callback to run after painting the UI. If none changed, React skips running the effect. This comparison happens during the render phase but the effect runs after the DOM updates.
Why designed this way?
React was designed to be declarative and efficient. Running effects only when needed avoids wasted work and bugs from stale data. The dependency array gives developers control over when side effects run, balancing flexibility and performance. Alternatives like running effects every render were too costly, and manual control without dependencies was error-prone.
Render Phase
┌─────────────────────────────┐
│ Component renders            │
│ React compares dependencies  │
│ with previous values         │
└─────────────┬───────────────┘
              │
              ▼
  ┌─────────────────────────┐
  │ Any dependency changed? │──No──▶ Skip effect
  └─────────────┬───────────┘
                │Yes
                ▼
  ┌─────────────────────────┐
  │ Schedule effect callback │
  │ to run after DOM update  │
  └─────────────────────────┘
Myth Busters - 4 Common Misconceptions
Quick: Does an empty dependency array mean the effect runs every render? Commit yes or no.
Common Belief:An empty dependency array means the effect runs every time the component renders.
Tap to reveal reality
Reality:An empty dependency array means the effect runs only once after the first render.
Why it matters:Believing this causes confusion and misuse of effects, leading to repeated work and bugs.
Quick: If you omit the dependency array, does useEffect run only once or every render? Commit your answer.
Common Belief:If you omit the dependency array, useEffect runs only once like with an empty array.
Tap to reveal reality
Reality:If you omit the dependency array, useEffect runs after every render.
Why it matters:This can cause performance issues and unexpected behavior if effects run too often.
Quick: Should you always include functions in the dependency array? Commit yes or no.
Common Belief:Functions used inside useEffect should always be included in the dependency array.
Tap to reveal reality
Reality:Including functions often causes effects to run every render because functions change identity; useCallback or other patterns are needed.
Why it matters:Not knowing this leads to infinite loops or excessive effect runs.
Quick: Does React automatically detect all dependencies inside useEffect? Commit yes or no.
Common Belief:React automatically tracks all variables used inside useEffect without needing a dependency array.
Tap to reveal reality
Reality:React relies entirely on the dependency array; it does not track variables automatically.
Why it matters:Missing dependencies cause stale closures and bugs that are hard to debug.
Expert Zone
1
Dependency arrays use Object.is for comparison, which differs from === in subtle ways, affecting when effects run.
2
Sometimes you intentionally omit dependencies and disable lint warnings to avoid unwanted effect runs, but this requires deep understanding.
3
Using refs inside effects can help avoid adding certain dependencies, balancing correctness and performance.
When NOT to use
Dependency arrays are not suitable for effects that must run on every render regardless of changes, such as animations or logging every render. In those cases, omit the dependency array or use other hooks like useLayoutEffect. Also, for complex dependencies like objects or arrays, shallow comparison in dependency arrays can cause bugs; useMemo or custom comparison may be better.
Production Patterns
In production, developers use exhaustive-deps lint rules to catch missing dependencies, memoize functions with useCallback, and memoize values with useMemo to control effect runs. Custom hooks often accept dependencies as parameters to keep effects predictable. Teams establish conventions to handle intentional omissions and complex dependencies safely.
Connections
Memoization
Dependency arrays often work with memoization techniques like useMemo and useCallback to optimize when values or functions change.
Understanding dependency arrays helps grasp why memoization is needed to prevent unnecessary recalculations and effect runs.
Event-driven programming
Dependency arrays create a reactive pattern where code runs only when specific data changes, similar to event listeners reacting to events.
Seeing dependency arrays as a way to listen for changes deepens understanding of reactive programming principles.
Spreadsheet recalculation
Dependency arrays are like spreadsheet cells that recalculate only when their input cells change.
Knowing this connection clarifies how React optimizes updates by tracking dependencies like a spreadsheet tracks formulas.
Common Pitfalls
#1Effect runs infinitely due to missing memoization of functions in dependencies.
Wrong approach:useEffect(() => { doSomething(); }, [someFunction]);
Correct approach:const memoizedFunction = useCallback(() => { doSomething(); }, []); useEffect(() => { memoizedFunction(); }, [memoizedFunction]);
Root cause:Functions change identity every render unless memoized, causing effects to rerun endlessly.
#2Effect uses a state variable but does not list it in dependencies, causing stale data.
Wrong approach:useEffect(() => { console.log(count); }, []);
Correct approach:useEffect(() => { console.log(count); }, [count]);
Root cause:Not listing all used variables in dependencies leads to effects using outdated values.
#3Omitting dependency array to run effect once but effect runs every render.
Wrong approach:useEffect(() => { fetchData(); });
Correct approach:useEffect(() => { fetchData(); }, []);
Root cause:Without dependency array, useEffect runs after every render, not just once.
Key Takeaways
The dependency array controls when React hooks like useEffect run by listing values to watch for changes.
An empty dependency array runs the effect only once after the first render, similar to componentDidMount.
Always include all variables used inside the effect in the dependency array to avoid bugs with stale data.
Functions in dependencies should be memoized with useCallback to prevent infinite effect loops.
Understanding and correctly using dependency arrays is key to writing efficient, bug-free React components.