Skip to content

Bug: Updates within microtasks within useEffect are not batched at first but batched when updates, and always not batched within useLayoutEffect #24625

@iamyoki

Description

@iamyoki

React version: 18.1.0

This issue may be a bit similar to this one: #24365

Steps To Reproduce

Code Example

The following example sets the toggle to on when the count is updated and creates a microtask and sets the toggle to off, we can see the toggle log every time it renders.

  const [toggle, setToggle] = useState()
  const [count, setCount] = useState(0)

  useEffect(() => {
    setToggle('on')
    Promise.resolve().then(() => {
      setToggle('off')
    })
  }, [count])

  useEffect(() => {
    console.log(toggle)
  })

  return (
    <div className="App">
      <button onClick={() => setCount(count + 1)}>refresh</button>
    </div>
  )

Weird things (steps):

  1. Refresh the page, it prints undefined, undefined, on, off, so we know it's not batched.
  2. Click the button to update count, it prints off, so we know it's batched.
  3. Change useEffect to useLayoutEffect, and refresh the page, it's the same as step1 results, and click the button, it prints off, on, off, this result is very different from step2.

I think it's not normal because of inconsistent behavior.

Link to code example:

Same code in React18: https://codesandbox.io/s/react18-batching-problem-jtehj4?file=/src/App.js
Same code in React17: https://codesandbox.io/s/react17-batching-foo6fi?file=/src/App.js

Metadata

Metadata

Assignees

No one assigned

    Labels

    Resolution: StaleAutomatically closed due to inactivityStatus: UnconfirmedA potential issue that we haven't yet confirmed as a bug

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions