facebook/react
react-dom
Active contributors: gnoff, sebmarkbage, eps1lon, sophiebits, acdlite
Purpose
packages/react-dom/ is the browser DOM renderer — the package most React users actually import. It exposes the client mount API (createRoot, hydrateRoot), the streaming SSR drivers (react-dom/server.node, react-dom/server.edge, react-dom/server.browser, react-dom/server.bun), the static prerender drivers (react-dom/static.*), and the react-dom/client re-exports for flushSync/unstable_batchedUpdates/etc.
Most of the heavy lifting is not in this package. The DOM-specific reconciler host config — createInstance, appendChild, attribute setting, the synthetic event system, hoisting of <title>/<link>/etc., suspense-aware resource preloading — lives in the sibling package packages/react-dom-bindings/. react-dom re-exports a small surface that delegates to react-dom-bindings and react-reconciler.
Directory layout
packages/react-dom/
├── package.json # 30+ entry points
├── index.js / client.js / profiling.js
├── server.js / server.node.js / server.edge.js / server.browser.js / server.bun.js
├── static.js / static.node.js / static.edge.js / static.browser.js
├── unstable_server-external-runtime.js
├── unstable_testing.js
├── test-utils.js
└── src/
├── ReactDOMSharedInternals.js # the dispatcher + currentDispatcher
├── ReactDOMFB.js / ReactDOMFB.modern.js # Facebook-internal surface
├── ReactDOMReactServer.js # the server condition surface
├── client/
│ ├── ReactDOMClient.js # createRoot / hydrateRoot
│ ├── ReactDOMRoot.js # the implementation
│ └── ReactDOMDefaultTransitionIndicator.js
├── server/ # streaming SSR public API
│ ├── ReactDOMFizzServerNode.js # renderToReadableStream / renderToPipeableStream
│ ├── ReactDOMFizzServerEdge.js
│ ├── ReactDOMFizzServerBrowser.js
│ ├── ReactDOMFizzServerBun.js
│ ├── ReactDOMFizzStaticNode.js / Edge.js / Browser.js # prerender / resume
│ └── ReactDOMServerLegacy.js (deprecated)
├── events/ # public event-handling helpers (act, etc.)
├── shared/ # shared with react-dom-bindings
└── test-utils/ # exported test-only helpers
packages/react-dom-bindings/
└── src/
├── client/
│ ├── ReactFiberConfigDOM.js # the host config (createInstance, ...) — ~3,000 lines
│ ├── ReactDOMComponent.js # diffProperties, setInitialDOMProperties
│ ├── ReactDOMHostContext.js
│ ├── ReactDOMRoots.js / ReactDOMContainer.js
│ ├── ReactDOMSelection.js
│ ├── ReactInputSelection.js
│ └── ... (CSPropertyOperations, CSSPropertyOperations, etc.)
├── server/
│ ├── ReactFizzConfigDOM.js # the Fizz host config
│ ├── ReactFizzConfigDOMLegacy.js
│ └── ReactDOMFloatServer.js / ReactDOMResources.js # hoisting <link>, <title>, etc.
├── events/ # the synthetic event system
│ ├── ReactDOMEventListener.js
│ ├── DOMPluginEventSystem.js
│ └── plugins/ # SimpleEventPlugin, ChangeEventPlugin, ...
└── shared/Key abstractions
| Abstraction | File | Description |
|---|---|---|
createRoot(container, options?) |
packages/react-dom/src/client/ReactDOMRoot.js |
Returns a Root with .render(element) and .unmount(). Internally calls createContainer from the reconciler. |
hydrateRoot(container, element, options?) |
packages/react-dom/src/client/ReactDOMRoot.js |
Same idea, but ties to existing server-rendered DOM. |
flushSync(fn) |
re-exported from react-reconciler |
Runs fn and flushes any updates synchronously. |
renderToReadableStream(element, options?) |
packages/react-dom/src/server/ReactDOMFizzServerNode.js (and Edge/Browser/Bun) |
Streaming SSR. Returns a ReadableStream of HTML. |
renderToPipeableStream(element, options?) |
packages/react-dom/src/server/ReactDOMFizzServerNode.js |
Node-only variant returning { pipe, abort }. |
prerender(element, options?) |
packages/react-dom/src/server/ReactDOMFizzStaticNode.js (and Edge/Browser) |
Static prerender. May return a postponed state. |
resume(element, postponedState, options?) |
same files | Resumes a prerender that was previously postponed. New in 19.2. |
resumeAndPrerender(...) |
same | Variant that resumes and produces final HTML. |
prefetchDNS(href) / preconnect(href) / preload(href, options) / preinit(href, options) / preinitModule |
packages/react-dom-bindings/src/client/ReactDOMFloatClient.js |
Resource hints. The matching server functions are in the float server file. |
| Host config | packages/react-dom-bindings/src/client/ReactFiberConfigDOM.js |
The set of functions the reconciler calls into to mutate the DOM. |
| Synthetic events | packages/react-dom-bindings/src/events/ |
Pluggable event system: SimpleEventPlugin, ChangeEventPlugin, EnterLeaveEventPlugin, SelectEventPlugin, BeforeInputEventPlugin. |
How it works
graph LR UserCode[root.render <App/>] --> ReactDOMRoot[ReactDOMRoot.js] ReactDOMRoot -->|updateContainer| Reconciler[react-reconciler] Reconciler -->|host config calls| HostConfig[react-dom-bindings/ReactFiberConfigDOM.js] HostConfig -->|createElement, appendChild, ...| DOM[(window.document)] Reconciler -->|event priority| EventSys[react-dom-bindings/events/*] EventSys -->|dispatch| UserCode
The DOM event system is renderer-aware: it asks the reconciler for the current event priority before dispatching, so a click becomes SyncLane work, a scroll becomes InputContinuousLane work, etc. See packages/react-dom-bindings/src/events/ReactDOMEventListener.js and the priority mapping in packages/react-reconciler/src/ReactEventPriorities.js.
Resource hoisting (Float)
The hoisting system promotes certain elements from inside the component tree into <head>:
<title>,<meta>,<link rel="stylesheet">,<link rel="preload">,<script async>.
The client side is packages/react-dom-bindings/src/client/ReactDOMFloatClient.js; the server side is packages/react-dom-bindings/src/server/ReactDOMFloatServer.js. Hoisting is coordinated with Suspense — boundaries that suspend block their resources so the page doesn't show partial state.
Two server engines, one package
Historically react-dom had two server engines:
- The legacy synchronous
ReactDOMStringRenderer(deprecated and removed). - Fizz — the streaming engine. Fizz lives in
packages/react-server/src/ReactFizzServer.js;react-dom/server.*are thin platform-specific drivers that supply Fizz with a host config (packages/react-dom-bindings/src/server/ReactFizzConfigDOM.js) and a stream config (packages/react-server/src/ReactServerStreamConfigNode.js,Edge.js,Browser.js,Bun.js).
The prerender/resume pair extends Fizz with a "postpone here" primitive that lets you split a render across machines or requests.
Integration points
react-reconciler—react-domcallsReconciler({...DOMHostConfig})exactly once at module load. The DOM host config is built up fromreact-dom-bindings/src/client/ReactFiberConfigDOM.jsplus the various capability shims (ReactFiberConfigWithNoMutationis not used here — DOM uses mutation mode).react-server— the SSR drivers inreact-dom/src/server/importReactFizzServer.jsfromreact-server.scheduler— used indirectly viareact-reconciler'sScheduler.jsshim. The DOM event system asks the scheduler forgetCurrentTimeandunstable_NormalPriority.react—react-dom-bindingsinstalls its dispatcher intoReactSharedInternalsduring render and removes it after.
Entry points for modification
- Adding an attribute or property handler:
packages/react-dom-bindings/src/client/ReactDOMComponent.jsis where the bigsetInitialProperties/updateDOMPropertiesswitches live, plus the boolean-attribute table (packages/react-dom-bindings/src/shared/DOMProperty.js). The matching server code is inpackages/react-dom-bindings/src/server/ReactFizzConfigDOM.js. - Adding a new resource type to hoist: edit both
ReactDOMFloatClient.jsandReactDOMFloatServer.js, and update the matchingReactFizzConfigDOM.jsserver emit. - Changing event behavior: the dispatcher is
ReactDOMEventListener.js; per-event-name behavior is the plugin inreact-dom-bindings/src/events/plugins/. - Adding a new server entry point (e.g. a new platform): add a new
ReactDOMFizzServer<Platform>.jsand a matchingReactServerStreamConfig<Platform>.js.
Related pages
- react-reconciler — the engine
react-domplugs into. - react-server — Fizz and Flight, both of which
react-dom's server drivers use. - features/server-components — end-to-end RSC pipeline.
Built by Factory AutoWiki from public repository content. It is a generated preview for codebase exploration, not source-maintained documentation.