facebook / react

The library for web and native user interfaces.
https://react.dev
MIT License
228.59k stars 46.79k forks source link

Bug: multiple useTransition hook in a page turn to activate first one #31312

Open SammuelChang opened 2 days ago

SammuelChang commented 2 days ago

React version: 18.0.0

Steps To Reproduce

As below codesandbox link

  1. Click StartTransition2 button
  2. see console show 'isPending true; isPending false'

Link to code example: https://codesandbox.io/p/sandbox/usetransition-issue-68tfls?file=/src/App.js

The current behavior

  1. Click StartTransition2 button
  2. see console show 'isPending true; isPending false'

The expected behavior

  1. Click StartTransition2 button
  2. see console show 'isPending2 true; isPending2 false'

Note

Actually, I'm not really sure it's a bug or mine misunderstanding. While hook is executed in function component by order (e.g. useState), each state hook memorize its own value, useTransition hook not do this in same way. I found it in another project, and simplify to codesandbox. The reason why I use two because I have two section in viewport relying on two sources (API) with different responding speed. I intend to let first response data show immediately and the other keep loading status by useTransition.

deepakb commented 5 hours ago

The issue arises because the second button is using the same startTransition as the first button. This means that both buttons are controlling the same isPending state, which is why isPending changes for both buttons, but isPending2 is never triggered.

To fix this, you need to update the second button to use startTransition2 and isPending2, like this:

<button
  disabled={isPending2} // Disable based on isPending2, not isPending
  className="border rounded-md"
  onClick={() => {
    startTransition2(async () => {  // Use startTransition2 here
      await fetch("https://api.thecatapi.com/v1/images/search?limit=100");
      setCount2((c) => c + 1);
      console.log("Success");
    });
  }}
>
  StartTransition2
</button>

This will ensure that the transitions are isolated properly, and each button will control its own pending state independently (isPending for the first button and isPending2 for the second).