In the docs: https://beta.reactjs.org/reference/react/useTransition#preventing-unwanted-loading-indicators
There's an example of a tab component that only shows up when it has finished loading all its data. Before it's finished, we still see the previously selected tab.
Something quirky is happening here, the TabButtons
are aware of the new tab
state and change their appearance, but in the rest of the JSX it seems we still work with the old value of tab
- because we still see the previously selected tab, instead of no tab at all, or a spinner.
It seems that the tab
state can have two values at the same time, in the same JSX statement.
See here, this is the code from the docs with a few things added to help in debugging: https://codesandbox.io/s/how-does-usetransition-work-n2vc9x?file=/App.js
Something quirky is happening here, the TabButtons are aware of the new tab state and change their appearance
Not all of the TabButtons are updating at this point, just the one in which you called startTransition
. Notice that About
is still in bold during this time; it's not yet a button.
What's happening is this:
startTransition(() => { onClick(); });
, and since onClick sets state, this requests a low priority rerender of App
TabButton
that called startTransition
. During this render, It's still getting the old isActive
prop which says it is not active, but useTransition
returns true
for isPending
. As a result, it renders a <b className="pending">
.tab
state and passes isActive
props to the tabs based on that. However, because the data in PostsTab
is not yet loaded, this render has to abort. It falls back to the suspense, but because of the transition, suspense will keep whatever is already mounted (it doesn't use the loading fallback).