DeployU
Interviews / Frontend Engineering / This button should increment twice, but only increments once. How do you fix it?

Questions

This button should increment twice, but only increments once. How do you fix it?

debugging State Management Interactive Quiz Code Examples

A developer has a Counter component with a “Double Increment” button. The intention is that when this button is clicked, the counter’s value should increase by 2.

They’ve implemented this by calling setCount(count + 1) twice in the same event handler. However, they notice a bug: clicking the “Double Increment” button only increments the count by 1, not by 2.

You’ve been given the Counter component.

  1. Explain why calling setCount(count + 1) twice in a row only increments the count by 1.
  2. Fix the component to correctly increment the counter by 2 with a single button click.
Your Code
import React, { useState } from 'react';

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

  const handleDoubleIncrement = () => {
    // THE BUG: Calling setCount with a direct value multiple times
    // in the same event handler.
    setCount(count + 1); // React sees count as 0, schedules update to 1
    setCount(count + 1); // React still sees count as 0, schedules update to 1 again
  };

  return (
    <div style={{ padding: '20px' }}>
      <h1>Count: {count}</h1>
      <button onClick={handleDoubleIncrement}>Double Increment</button>
      <p>Click the button and observe the count.</p>
    </div>
  );
}
Click "Run Code" to see output...
Click "Run Code" to see test results...
Wrong Approach

Calling `setCount(count + 1)` twice uses the same stale count value from the current render closure. Both calls schedule updates to the same value, and React batches them, resulting in only one increment.

Right Approach

Use the functional update form `setCount(prevCount => prevCount + 1)`. Each call receives the most recent state value as an argument, ensuring sequential updates are applied correctly even when batched.

The bug occurs because React’s state updates (triggered by setCount) are asynchronous and often batched for performance reasons.

When handleDoubleIncrement is called:

  1. setCount(count + 1): At this point, count is 0. React schedules an update to set count to 1.
  2. setCount(count + 1): Immediately after, this line is executed. Crucially, count in this line still refers to the value from the current render scope, which is 0. So, React schedules another update to set count to 1.

Because React batches these updates, it sees two requests to set count to 1. The second request effectively overwrites the first, resulting in the count only increasing by 1.

To ensure that state updates are based on the most recent state, you should use the functional update form of setCount (or setState in class components). This form passes a function to setCount, and that function receives the prevState as its argument. React guarantees that prevState will always be the latest available state.

Here is the corrected implementation:

import React, { useState } from 'react';

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

  const handleDoubleIncrement = () => {
    // FIX: Use the functional update form to ensure each update
    // is based on the previous state.
    setCount(prevCount => prevCount + 1); // Schedules update based on prevCount
    setCount(prevCount => prevCount + 1); // Schedules another update based on the result of the first
  };

  return (
    <div style={{ padding: '20px' }}>
      <h1>Count: {count}</h1>
      <button onClick={handleDoubleIncrement}>Double Increment</button>
      <p>Click the button and observe the count.</p>
    </div>
  );
}

By using setCount(prevCount => prevCount + 1), each call to setCount now correctly receives the result of the previous state update, ensuring that the counter increments by 2.

Practice Question

When should you use the functional update form of `setCount` (e.g., `setCount(prevCount => prevCount + 1)`)?