React: Hooks: Calling setState with the SAME value multiple times, evaluates the component function up-to 2 times

Created on 27 Nov 2019  路  4Comments  路  Source: facebook/react

Do you want to request a feature or report a bug?

Bug

What is the current behavior?

Using the State hook, calling setXYZ() with the same value multiple times causes the component function to be evaluated more than once (up-to 2 times). I don't mean re-rendered, but a re-evaluation of its function.

Scenario 1 (OK):

  • the component function is evaluated, initial render useState(1)
  • click button => setState(1)
  • the component function is not re-evaluated. :heavy_check_mark:
  • click button again => setState(1)
  • the component function is not re-evaluated.
  • click button again => setState(1)
  • the component function is not re-evaluated.
  • etc.

Scenario 2:

  • the component function is evaluated, initial render useState(1)
  • click button => setState(2)
  • the component function IS re-evaluated, component re-rendered :heavy_check_mark:
  • click button again => setState(2)
  • the component function IS evaluated AGAIN :negative_squared_cross_mark:
  • click button again => setState(2)
  • the component function is not re-evaluated.
  • click button again => setState(2)
  • the component function is not re-evaluated.
  • etc.

If the current behavior is a bug, please provide the steps to reproduce and if possible a minimal demo of the problem. Your bug will get fixed much faster if we can run your code and it doesn't have dependencies other than React. Paste the link to your JSFiddle (https://jsfiddle.net/Luktwrdm/) or CodeSandbox (https://codesandbox.io/s/new) example below:

https://jsfiddle.net/qf103zvj/

What is the expected behavior?

Just as Scenario 1, I'd expect ONLY one re-evaluation of the component function.

Scenario 2:

  • the component function is evaluated, initial render useState(1)
  • click button => setState(2)
  • the component function IS re-evaluated, component re-rendered :heavy_check_mark:
  • click button again => setState(2)
  • the component function is not re-evaluated. :heavy_check_mark:
  • click button again => setState(2)
  • the component function is not re-evaluated.
  • etc.

Which versions of React, and which browser / OS are affected by this issue? Did this work in previous versions of React?

Chrome 78, Firefox 70, React 16; Both macOS, Linux. Unsure about previous versions of React.

Stale

Most helpful comment

This is a known quirk due to the implementation details of concurrency in React. We don't cheaply know which of two versions is currently committed. When this ambiguity happens we have to over render once and after that we know that both versions are the same and it doesn't matter.

All 4 comments

Interesting discovery. This certainly doesn't look like a useful feature.

This is a known quirk due to the implementation details of concurrency in React. We don't cheaply know which of two versions is currently committed. When this ambiguity happens we have to over render once and after that we know that both versions are the same and it doesn't matter.

I encountered the same thing while trying to understand React hooks better.

Check out this fiddle, and open up the Console tab. https://jsfiddle.net/devotis/jd12g7y4/

In that fiddle, the App function is run one extra time after calling setValue with the same value, but the result of the last function call, is not being sent to the dom. Also notice how useEffect is not calling its function after that last function call (which makes sense, because there wasn't any effect in the dom with that last function call).

I do not consider this a bug. Just something I didn't expect at the time. To be precise; I didn't expect the App function to be called the last time (when setValue was called with the same value). The explanation by @sebmarkbage makes sense though. Is this behaviour documented somewhere?

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contribution.

Was this page helpful?
0 / 5 - 0 ratings