Why is my React component not re-rendering after state update?

I'm updating state in a React component using useState, but the component is not re-rendering. What could be causing this?

Solution

  1. State Mutation: Ensure you are not mutating the state directly. Always use the setter function:
const [count, setCount] = useState(0);
setCount(count + 1); // ✅ Correct

instead of:

count++; // ❌ Wrong (mutating state)
  1. Same State Value: If React sees the new state as identical to the previous one, it won’t trigger a re-render. Try logging the state values to check.
  2. Asynchronous Updates: React batches state updates. If you're setting state inside an event handler, wrap it in a function:
setCount(prevCount => prevCount + 1);
  1. Component Not Re-Rendering: If you are using React.memo or PureComponent, check if props/state are actually changing.
Alternative #1

One thing that always trips people up is the object/array reference problem. Even if you think you're updating state correctly, React might not see it as a change.

Here's a common pattern I see:

const [user, setUser] = useState({ name: 'John', age: 30 });

// ❌ This won't trigger a re-render
user.age = 31;
setUser(user);

// ✅ This will work
setUser({ ...user, age: 31 });

The same applies to arrays:

const [items, setItems] = useState(['a', 'b', 'c']);

// ❌ Won't re-render
items.push('d');
setItems(items);

// ✅ Will re-render
setItems([...items, 'd']);

React uses Object.is() for comparison, so it needs to see a new reference to trigger a re-render. This is probably the most common cause of "my state isn't updating" issues.

Alternative #2

Another thing to check - are you setting state inside a useEffect without proper dependencies? I've seen this pattern cause issues:

useEffect(() => {
  setCount(count + 1); // This might not work as expected
}, []); // Empty dependency array

If you need to update state based on props or other state, make sure your dependencies are correct:

useEffect(() => {
  setCount(prevCount => prevCount + 1); // Use functional update
}, [someProp]); // Include actual dependencies

Also, check if you're setting state in an async function without proper cleanup:

useEffect(() => {
  let isMounted = true;
  
  async function fetchData() {
    const data = await api.getData();
    if (isMounted) {
      setData(data); // Only update if component is still mounted
    }
  }
  
  fetchData();
  
  return () => {
    isMounted = false;
  };
}, []);

This prevents setting state on unmounted components, which can cause weird behavior.

Alternative #3

Sometimes the issue isn't with state at all - it's with how you're checking if the component re-rendered. I've spent hours debugging what I thought was a state issue, only to realize the component was actually re-rendering but the UI wasn't updating as expected.

Try adding some debugging:

const [count, setCount] = useState(0);

console.log('Component rendered, count:', count);

useEffect(() => {
  console.log('Count changed to:', count);
}, [count]);

Also, check if you're using React.StrictMode in development - it intentionally double-renders components to help catch side effects. This can be confusing if you're not expecting it.

If the console shows the component is re-rendering but the UI isn't updating, the issue might be:

  • CSS hiding the element
  • Conditional rendering logic
  • Parent component not passing updated props
  • Stale closures in event handlers

Don't assume it's always a state problem!

Last modified: March 31, 2025