为何无状态变更时startTransition仍会触发高优先级更新与重渲染?
Let’s tackle your questions one by one, using your example code as a reference:
Why does a re-render happen even with an empty callback?
When you call startTransition, React doesn’t just run your callback—it also manages an internal state tracked by the isPending value returned from useTransition. Here’s the step-by-step sequence when you click the button:
- Right after invoking
startTransition, React updatesisPendingtotrueto signal a transition is underway. This triggers a high-priority re-render—it’s React’s way of letting you show immediate user feedback (like a loading spinner) if you use theisPendingvalue. - It then executes your empty callback. Since there are no state updates inside, no additional business logic runs here.
- Once the callback finishes, React flips
isPendingback tofalseto mark the transition as complete. This triggers a second, low-priority re-render.
That’s why you see the render log twice: two separate state changes to the internal isPending value are driving the re-renders, even when your custom callback does nothing.
Is this re-render a high-priority update?
Not exactly—there are two distinct re-renders here, each with different priorities:
- The first re-render (when
isPendingswitches totrue) is indeed a high-priority update. React prioritizes this because immediate feedback is critical for a responsive UI—users need to know their action was registered right away. - The second re-render (when
isPendingreverts tofalse) is a low-priority update, part of the transition queue. This one can be interrupted by higher-priority work (like another user click) if needed.
The blog post mentioning a high-priority update is referring to that initial pending-state re-render, which is accurate—but it only covers half the picture.
Does this violate startTransition’s design purpose?
No, this behavior aligns perfectly with its intended use. startTransition is designed to mark your application state updates as low-priority, but it needs to manage internal state to enable transition tracking. The high-priority update to isPending is a necessary implementation detail:
- It lets you build responsive UIs by showing pending states immediately.
- It doesn’t interfere with the low-priority handling of any state updates you do put inside the callback.
Think of it this way: React uses that high-priority update to "bookend" the transition, giving you visibility into its progress without blocking the main thread for non-urgent work.
Example Breakdown
Looking at your code snippet:
export default function App() { const [isPending, startTransition] = useTransition(); console.log("render"); return ( <button onClick={() => startTransition(() => {})}> Start Transition </button> ); }
Clicking the button will log render twice: once when isPending becomes true (high-priority), and once when it goes back to false (low-priority).
内容的提问来源于stack exchange,提问作者user3257598

