Blog>
Snippets

Debugging State Reactivity

Demonstrate troubleshooting a common reactivity issue where updates to the store state do not trigger UI updates as expected.
const { useState } = require('react');
const useCustomHook = () => {
  const [state, setState] = useState({ count: 0 });
  const increment = () => {
    // Incorrectly mutating the state object directly
    state.count += 1;
    // Correct approach is to use setState
    // setState({ count: state.count + 1 });
    console.log(state.count); // This will log increased count but won't trigger re-render
  };

  return { state, increment };
};
This snippet demonstrates an attempt to update the state directly which is a common mistake. React state updates should always be immutable, using methods like setState, to ensure components re-render. The correct approach using setState is commented out.
function App() {
  const { state, increment } = useCustomHook();
  
  return (
    <div>
      <p>{state.count}</p>
      <button onClick={increment}>Increment</button>
    </div>
  );
}
This component attempts to use the custom hook 'useCustomHook'. However, due to the direct mutation of the state in 'useCustomHook', changes to 'state.count' won't cause the component to re-render as expected when the 'Increment' button is clicked.
const useCorrectCustomHook = () => {
  const [state, setState] = useState({ count: 0 });
  const increment = () => {
    // Correctly using setState to ensure immutability and trigger re-render
    setState(prevState => ({ count: prevState.count + 1 }));
  };

  return { state, increment };
};
This corrected hook uses setState in a way that respects immutability. By using a function that takes the previous state and returns a new state, we ensure that the component consuming this hook will re-render correctly on state changes.