Skip to content

Bug: [React 18] act in tests can alter autobatching behavior compared to production in 18.3.1 #33479

Open
@truongnguyen-eh

Description

@truongnguyen-eh

React version: 18.3.1

Steps To Reproduce

Please refer to the CodeSandbox link below for a complete repro.

  1. Trigger a fetch request by clicking a button that internally calls two setState calls: setIsLoading(true) followed by setIsLoading(false) once the API call completes.
  2. Use act to mimic the behavior in a test using React Testing Library:
<button
    onClick={async () => {
      act(() => {
        handleClick();
      });
      await act(async () => {
        await waitForAPICall();
      });
    }}
  >

Link to code example: https://codesandbox.io/p/devbox/practical-neumann-g82dcv?workspaceId=ws_8edRzHnWwZWJh5UnZUEo7c

The current behavior

  • We see Trigger onComplete callback for fetch API is not logged in the console, because setIsLoading(true) and setIsLoading(false) are batched into a single render, causing the callback of useEffect not to run.

  • This behavior does not match the production app (act is not used), where the two state updates trigger separate renders as expected.

  • Removing act from the logic results in two renders, though it causes a React warning ("Warning: An update to App inside a test was not wrapped in act(...)") in tests.

Additional observations:

  • If I don't await fetch params before the setIsLoading(true) call (No await getFetchParams()), the test still causes two re-renders, even inside act.

  • This issue does not occur when upgrading to React 19.1.0.

Based on these observations, it appears that using act in tests can alter the autobatching behavior in React 18.3.1, potentially reducing test reliability.

The expected behavior

  • Using act in tests should preserve the same autobatching behavior seen in production.
  • In this case, setIsLoading(true) and setIsLoading(false) should result in two separate renders inside tests, just as they do in a real app.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Status: 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