mirror of
https://github.com/facebook/react.git
synced 2025-11-01 09:12:30 +00:00
Note: Despite the similar-sounding description, this fix is unrelated to
the issue where updates that occur after an `await` in an async action
must also be wrapped in their own `startTransition`, due to the absence
of an AsyncContext mechanism in browsers today.
---
Discovered a flaw in the current implementation of the isomorphic
startTransition implementation (React.startTransition), related to async
actions. It only creates an async scope if something calls setState
within the synchronous part of the action (i.e. before the first
`await`). I had thought this was fine because if there's no update
during this part, then there's nothing that needs to be entangled. I
didn't think this through, though — if there are multiple async updates
interleaved throughout the rest of the action, we need the async scope
to have already been created so that _those_ are batched together.
An even easier way to observe this is to schedule an optimistic update
after an `await` — the optimistic update should not be reverted until
the async action is complete.
To implement, during the reconciler's module initialization, we compose
its startTransition implementation with any previous reconciler's
startTransition that was already initialized. Then, the isomorphic
startTransition is the composition of every
reconciler's startTransition.
```js
function startTransition(fn) {
return startTransitionDOM(() => {
return startTransitionART(() => {
return startTransitionThreeFiber(() => {
// and so on...
return fn();
});
});
});
}
```
This is basically how flushSync is implemented, too.
react-dom
This package serves as the entry point to the DOM and server renderers for React. It is intended to be paired with the generic React package, which is shipped as react to npm.
Installation
npm install react react-dom
Usage
In the browser
import { createRoot } from 'react-dom/client';
function App() {
return <div>Hello World</div>;
}
const root = createRoot(document.getElementById('root'));
root.render(<App />);
On the server
import { renderToPipeableStream } from 'react-dom/server';
function App() {
return <div>Hello World</div>;
}
function handleRequest(res) {
// ... in your server handler ...
const stream = renderToPipeableStream(<App />, {
onShellReady() {
res.statusCode = 200;
res.setHeader('Content-type', 'text/html');
stream.pipe(res);
},
// ...
});
}
API
react-dom
See https://react.dev/reference/react-dom
react-dom/client
See https://react.dev/reference/react-dom/client