Re-render Triggers

Med

Understanding what causes React components to re-render is critical for performance and debugging. A component re-renders when its state changes, when its parent re-renders, or when a context it consumes changes. Knowing these triggers helps you prevent unnecessary renders.

Interactive Visualization

Key Points

  • State change: calling setState with a new value triggers a re-render
  • Parent re-render: all children re-render by default when a parent re-renders
  • Context change: all consumers of a context re-render when the provider value changes
  • Same state value: React bails out if the new state is the same reference (Object.is)
  • Props alone do not trigger re-renders; the parent re-rendering does
  • React.memo wraps a component to skip re-rendering when props have not changed
  • forceUpdate in class components has no functional component equivalent

Code Examples

Identifying Re-render Causes

import { useState, memo } from 'react'

function Parent() {
  const [count, setCount] = useState(0)
  const [name, setName] = useState('Alice')

  return (
    <div>
      <button onClick={() => setCount((c) => c + 1)}>
        Count: {count}
      </button>

      {/* Re-renders on every count change even though it only uses name */}
      <Child name={name} />

      {/* Skips re-render when name has not changed */}
      <MemoizedChild name={name} />
    </div>
  )
}

function Child({ name }: { name: string }) {
  return <div>Hello {name}</div>
}

const MemoizedChild = memo(function MemoizedChild({ name }: { name: string }) {
  return <div>Hello {name}</div>
})

Child re-renders every time Parent re-renders regardless of which state changed; MemoizedChild skips re-rendering when its name prop has not changed

State Bailout

import { useState } from 'react'

function Counter() {
  const [count, setCount] = useState(0)

  const handleClick = () => {
    // Setting the same value: React bails out, no re-render
    setCount(0) // No re-render if count is already 0

    // New reference: always triggers re-render
    // setData({ ...data }) // Creates a new object, triggers re-render
    // setData(data)        // Same reference, bails out
  }

  return <button onClick={handleClick}>Count: {count}</button>
}

React uses Object.is to compare the new value with the current value; if they are the same, the re-render is skipped

Common Mistakes

  • Creating new object or array references on every render that break memoization
  • Assuming props changes cause re-renders when it is actually the parent re-rendering
  • Placing rapidly changing state high in the tree causing the entire subtree to re-render

Interview Tips

  • List the three triggers: state change, parent re-render, context change
  • Explain why passing inline objects or functions as props breaks React.memo
  • Discuss the composition pattern of moving state closer to where it is used

Related Concepts