This page explains how the React reconciler abstracts over its host environment through the ReactFiberConfig interface. It covers the module-fork pattern, every method group the interface defines, the "No*" shim modules for optional capabilities, and the concrete implementations for each first-party renderer. For details about how the DOM renderer specifically implements each method, see 6.1. For the hydration-specific subset of this interface, see 6.4. For View Transition and gesture hooks, see 6.5.
The reconciler in react-reconciler is host-agnostic. It drives the Fiber work loop, schedules updates, runs hooks, and manages tree structure—but every side-effectful interaction with the target platform (creating DOM nodes, calling native UIManager APIs, writing to a test in-memory tree) is delegated to a host configuration module.
Inside the reconciler source, all host interactions are imported from a single logical module called ReactFiberConfig. At build time or at package entry, this module is swapped for an environment-specific implementation. There is one implementation per renderer:
| Renderer | Host Config File |
|---|---|
| React DOM (client) | packages/react-dom-bindings/src/client/ReactFiberConfigDOM.js |
| React Native Paper | packages/react-native-renderer/src/ReactFiberConfigNative.js |
| React Native Fabric | packages/react-native-renderer/src/ReactFiberConfigFabric.js |
| Test Renderer | packages/react-test-renderer/src/ReactFiberConfigTestHost.js |
| Noop Renderer | packages/react-noop-renderer/src/createReactNoop.js (inline object) |
| React ART | packages/react-art/src/ReactFiberConfigART.js |
| Third-party (npm) | packages/react-reconciler/src/forks/ReactFiberConfig.custom.js |
Sources: packages/react-reconciler/src/forks/ReactFiberConfig.custom.js1-50
The reconciler itself does not ship with a bound host config. Instead, the build system replaces all import … from './ReactFiberConfig' statements with a resolved path depending on the build target.
For first-party renderers (DOM, Native, Test), Rollup or Metro resolves ReactFiberConfig to the renderer's own file before bundling.
For the public react-reconciler npm package, the bundle is wrapped in a factory function:
module.exports = function ($$$config) {
/* reconciler code */
};
The file packages/react-reconciler/src/forks/ReactFiberConfig.custom.js is what the reconciler "sees" during compilation. Every export in that file simply forwards to the $$$config argument:
This means callers of the npm package pass a plain object as $$$config when invoking the factory.
Sources: packages/react-reconciler/src/forks/ReactFiberConfig.custom.js10-30 packages/react-reconciler/src/forks/ReactFiberConfig.custom.js52-287
Diagram: ReactFiberConfig Resolution at Build Time
Sources: packages/react-reconciler/src/forks/ReactFiberConfig.custom.js10-30 packages/react-dom-bindings/src/client/ReactFiberConfigDOM.js1-10 packages/react-native-renderer/src/ReactFiberConfigNative.js1-10 packages/react-test-renderer/src/ReactFiberConfigTestHost.js1-10
Every host config is expected to declare opaque types that name the platform-specific representations. The reconciler uses these types internally but never inspects their structure.
| Type Export | What It Represents |
|---|---|
Type | The element type tag (e.g., string for DOM tags) |
Props | The element's props object |
Container | The root mount point (e.g., DOM Element, RN container tag) |
Instance | A host component instance (e.g., DOM Element, RN shadow node) |
TextInstance | A host text node |
SuspenseInstance | A server-rendered Suspense boundary marker |
ActivityInstance | A server-rendered Activity boundary marker |
HydratableInstance | Union of all hydratable node types |
PublicInstance | What refs expose to user code |
HostContext | Opaque context threaded through the tree during render |
UpdatePayload | The result of diffing old/new props for mutation |
ChildSet | Used in persistence mode only |
TimeoutHandle / NoTimeout | Timer handle types |
SuspendedState | State object for suspensey commits |
RunningViewTransition | Handle to an active view transition |
ViewTransitionInstance | Ref-exposed view transition handle |
InstanceMeasurement | Snapshot of an instance's size/position |
FragmentInstanceType | Ref-exposed handle for fragment refs |
GestureTimeline | A timeline object for gesture-driven transitions |
In the DOM implementation, most of these resolve to concrete Web API types. In the custom fork, all are declared as opaque type … = mixed since they are entirely user-defined.
Sources: packages/react-reconciler/src/forks/ReactFiberConfig.custom.js27-52 packages/react-dom-bindings/src/client/ReactFiberConfigDOM.js154-260 packages/react-native-renderer/src/ReactFiberConfigFabric.js96-153 packages/react-test-renderer/src/ReactFiberConfigTestHost.js28-57
The interface is divided into a required core and several optional capability groups. A renderer declares which optional capabilities it supports via boolean flags (supportsMutation, supportsPersistence, supportsHydration, etc.). For capabilities it does not implement, it re-exports stubs from a corresponding ReactFiberConfigWithNo*.js shim.
Diagram: Host Config Method Groups and Key Methods
Sources: packages/react-reconciler/src/forks/ReactFiberConfig.custom.js56-286
These methods must be implemented by every renderer.
Context propagation
| Method | Called by | Purpose |
|---|---|---|
getRootHostContext(rootContainer) | beginWork | Returns the initial HostContext for the root |
getChildHostContext(parentCtx, type) | beginWork | Returns a (possibly updated) context for a child host component |
In the DOM renderer, HostContext encodes the current XML namespace (HTML, SVG, MathML) to determine how to create child elements. In React Native, it carries {isInAParentText: boolean} to enforce that raw text appears inside a <Text>.
Instance lifecycle
| Method | Purpose |
|---|---|
createInstance(type, props, rootContainer, hostContext, internalHandle) | Creates a new host instance (e.g., document.createElement) |
createTextInstance(text, rootContainer, hostContext, internalHandle) | Creates a text node |
appendInitialChild(parent, child) | Appends a child during the completeWork phase (tree is not yet mounted) |
finalizeInitialChildren(instance, type, props, hostContext) | Called after children are appended; returns true if commitMount should be scheduled |
shouldSetTextContent(type, props) | Returns true if the host handles text internally (e.g., <textarea> in DOM) |
cloneMutableInstance(instance, keepChildren) | Clones an instance for gesture transitions |
cloneMutableTextInstance(textInstance) | Clones a text instance for gesture transitions |
getPublicInstance(instance) | Returns the ref-accessible form of an instance |
Commit lifecycle
| Method | Purpose |
|---|---|
prepareForCommit(containerInfo) | Called before mutation phase; DOM implementation disables events and saves selection |
resetAfterCommit(containerInfo) | Called after mutation phase; DOM implementation restores events and selection |
Sources: packages/react-dom-bindings/src/client/ReactFiberConfigDOM.js303-411 packages/react-dom-bindings/src/client/ReactFiberConfigDOM.js413-451 packages/react-dom-bindings/src/client/ReactFiberConfigDOM.js485-609 packages/react-native-renderer/src/ReactFiberConfigNative.js264-295
These allow the host to report and manipulate the current event priority, bridging browser event context to React's lane model.
| Method | Purpose |
|---|---|
setCurrentUpdatePriority(priority) | Called by the event system to stamp incoming events |
getCurrentUpdatePriority() | Returns the priority stamped by the event system |
resolveUpdatePriority() | Returns the effective priority, falling back to event system priority if no explicit one is set |
trackSchedulerEvent() | Marks the current browser event so that follow-on events can be distinguished |
resolveEventType() | Returns the current browser event type (for transition tracking) |
resolveEventTimeStamp() | Returns the current browser event timestamp |
shouldAttemptEagerTransition() | Returns true during popstate events to attempt eager synchronous render |
Sources: packages/react-dom-bindings/src/client/ReactFiberConfigDOM.js757-770 packages/react-native-renderer/src/ReactFiberConfigFabric.js390-423 packages/react-test-renderer/src/ReactFiberConfigTestHost.js239-264
These methods give the host environment control over delaying the commit phase until resources (e.g., images) are loaded.
| Method | Purpose |
|---|---|
maySuspendCommit(type, props) | Returns true if this instance type can ever suspend commit |
maySuspendCommitOnUpdate(type, oldProps, newProps) | Returns true if an update could suspend commit (e.g., src change) |
maySuspendCommitInSyncRender(type, props) | Returns true if suspensey commit applies even in sync renders |
preloadInstance(instance, type, props) | Initiates preloading; returns true if already ready |
startSuspendingCommit() | Creates a SuspendedState accumulator |
suspendInstance(state, instance, type, props) | Subscribes to the instance's load event via the state object |
waitForCommitToBeReady(state, timeoutOffset) | Returns a function to register the commit callback, or null if ready immediately |
getSuspendedCommitReason(state, rootContainer) | Returns a debug string describing what is blocking the commit |
The Noop renderer exercises this full protocol with its suspensey-thing test element type.
Sources: packages/react-noop-renderer/src/createReactNoop.js316-373 packages/react-noop-renderer/src/createReactNoop.js618-703
Declared by supportsMutation = true. These methods mutate the live host tree in place and are used by the DOM and React Native Paper renderers.
| Method | Purpose |
|---|---|
appendChild(parent, child) | Move/append a child to a parent |
appendChildToContainer(container, child) | Append to the root container |
insertBefore(parent, child, before) | Insert before a sibling |
insertInContainerBefore(container, child, before) | Insert into root container before a sibling |
removeChild(parent, child) | Remove a child |
removeChildFromContainer(container, child) | Remove from root container |
commitMount(instance, type, props, handle) | Called on mount when finalizeInitialChildren returned true (e.g., auto-focus) |
commitUpdate(instance, type, oldProps, newProps, handle) | Apply prop diffs to an existing instance |
commitTextUpdate(textInstance, oldText, newText) | Update a text node's content |
resetTextContent(instance) | Clear text content before re-rendering children |
clearContainer(container) | Remove all children from a container |
hideInstance(instance) / unhideInstance(instance, props) | Toggle visibility for offscreen rendering |
hideTextInstance(textInstance) / unhideTextInstance(textInstance, text) | Same for text nodes |
The DOM renderer's appendChild also conditionally uses the experimental moveBefore() API when available to preserve element state during reparenting.
Sources: packages/react-dom-bindings/src/client/ReactFiberConfigDOM.js832-957 packages/react-dom-bindings/src/client/ReactFiberConfigDOM.js973-1115 packages/react-reconciler/src/ReactFiberConfigWithNoMutation.js1-62
Declared by supportsPersistence = true. Used by React Native Fabric. Instead of mutating live nodes, the reconciler builds a new immutable tree and atomically replaces the root's children.
| Method | Purpose |
|---|---|
cloneInstance(instance, type, oldProps, newProps, keepChildren, newChildSet) | Clone an immutable shadow node with updated props |
cloneHiddenInstance(instance, type, props) | Clone an instance in its hidden state |
cloneHiddenTextInstance(instance, text) | Clone a hidden text node |
createContainerChildSet() | Create an empty child set |
appendChildToContainerChildSet(childSet, child) | Accumulate children into the pending child set |
finalizeContainerChildren(container, newChildren) | Called with the completed new children before replacement |
replaceContainerChildren(container, newChildren) | Atomically apply the new children to the container |
In Fabric, replaceContainerChildren calls completeRoot(container.containerTag, newChildren) via nativeFabricUIManager.
Sources: packages/react-native-renderer/src/ReactFiberConfigFabric.js453-565 packages/react-noop-renderer/src/createReactNoop.js910-986
Renderers that do not support a capability re-export stubs from a corresponding shim. Each shim sets the capability flag to false and provides throwing functions for each method in that group.
| Shim File | Disables |
|---|---|
ReactFiberConfigWithNoMutation.js | supportsMutation = false, all mutation methods throw |
ReactFiberConfigWithNoPersistence.js | supportsPersistence = false, all persistence methods throw |
ReactFiberConfigWithNoHydration.js | supportsHydration = false, all hydration methods throw |
ReactFiberConfigWithNoMicrotasks.js | supportsMicrotasks = false, scheduleMicrotask throws |
ReactFiberConfigWithNoTestSelectors.js | supportsTestSelectors = false, selector methods throw |
ReactFiberConfigWithNoResources.js | supportsResources = false, resource methods throw |
ReactFiberConfigWithNoSingletons.js | supportsSingletons = false, singleton methods throw |
For example, the Fabric renderer re-exports all mutation shims and implements only persistence:
Sources: packages/react-reconciler/src/ReactFiberConfigWithNoMutation.js1-62 packages/react-native-renderer/src/ReactFiberConfigFabric.js163-168 packages/react-native-renderer/src/ReactFiberConfigNative.js115-121
Declared by supportsResources = true. Used exclusively by the DOM renderer to hoist <link>, <style>, and <script> tags into the document <head> and deduplicate them as shared resources.
Key methods: getHoistableRoot, getResource, acquireResource, releaseResource, mountHoistable, unmountHoistable, createHoistableInstance, prepareToCommitHoistables, hydrateHoistable, mayResourceSuspendCommit, preloadResource, suspendResource.
Sources: packages/react-dom-bindings/src/client/ReactFiberConfigDOM.js1-50 packages/react-reconciler/src/forks/ReactFiberConfig.custom.js260-275
Declared by supportsSingletons = true. Used by the DOM renderer to allow components like <head>, <html>, and <body> to be "adopted" rather than created fresh, since only one can exist in the document.
Key methods: resolveSingletonInstance, acquireSingletonInstance, releaseSingletonInstance, isHostSingletonType, isSingletonScope.
Sources: packages/react-dom-bindings/src/client/ReactFiberConfigDOM.js1117-1120 packages/react-reconciler/src/forks/ReactFiberConfig.custom.js280-286
These are declared within the mutation group (they require supportsMutation). They allow the host to participate in coordinating CSS View Transitions and gesture-driven animations.
| Method | Purpose |
|---|---|
applyViewTransitionName(instance, name, className) | Assign a view-transition-name CSS property to an element |
restoreViewTransitionName(instance, props) | Remove the assigned name, restoring original styles |
cancelViewTransitionName(instance, name, props) | Cancel an assigned name that won't be animated |
cancelRootViewTransitionName(rootContainer) | Cancel the root container's view transition name |
cloneRootViewTransitionContainer(rootContainer) | Clone the root for old/new state capture |
removeRootViewTransitionClone(rootContainer, clone) | Remove the cloned root after the transition |
measureInstance(instance) | Capture layout metrics before mutations |
measureClonedInstance(instance) | Measure a cloned instance |
wasInstanceInViewport(measurement) | Returns true if the instance was in the viewport at measurement time |
hasInstanceChanged(old, new) | Returns true if layout changed enough to warrant animation |
startViewTransition(rootContainer, types, mutationCb, layoutCb, ...) | Begin a CSS View Transition wrapping DOM mutations |
startGestureTransition(rootContainer, timeline, rangeStart, rangeEnd, ...) | Begin a gesture-controlled view transition |
stopViewTransition(transition) | Abort an active view transition |
addViewTransitionFinishedListener(transition, callback) | Notify when the transition animation completes |
createViewTransitionInstance(name) | Create a ViewTransitionInstance for a named boundary |
getCurrentGestureOffset(provider) | Read the current position (0–100) of a gesture timeline |
Non-DOM renderers (Native, Test, Noop) implement these as no-ops or minimal stubs, calling the mutation/layout callbacks directly without any animation.
Sources: packages/react-native-renderer/src/ReactFiberConfigNative.js594-691 packages/react-test-renderer/src/ReactFiberConfigTestHost.js335-468 packages/react-noop-renderer/src/createReactNoop.js799-909 packages/react-reconciler/src/ReactFiberConfigWithNoMutation.js39-62
Diagram: Renderer Capability Support
Sources: packages/react-dom-bindings/src/client/ReactFiberConfigDOM.js834-835 packages/react-native-renderer/src/ReactFiberConfigNative.js115-122 packages/react-native-renderer/src/ReactFiberConfigFabric.js163-168 packages/react-test-renderer/src/ReactFiberConfigTestHost.js59-65
HostContext is an opaque value threaded through beginWork from parent to child. The reconciler calls getRootHostContext once per root, then getChildHostContext on each host element to potentially produce a new context for its children.
Diagram: HostContext flow through Fiber tree
In the DOM, the context carries a HostContextNamespace value (0 = none, 1 = SVG, 2 = MathML) so that createInstance can call createElementNS with the right namespace. When entering a foreignObject inside SVG, the context resets back to HostContextNamespaceNone.
In React Native, the context carries {isInAParentText: boolean} to validate that raw text nodes appear only inside a <Text> component.
Sources: packages/react-dom-bindings/src/client/ReactFiberConfigDOM.js285-407 packages/react-native-renderer/src/ReactFiberConfigNative.js264-288 packages/react-native-renderer/src/ReactFiberConfigFabric.js262-295
These methods support the FragmentRef feature, which exposes a ref-accessible handle for Fragment fiber boundaries. Renderers that implement this fully (currently Fabric) create FragmentInstance objects backed by IntersectionObserver and DOM geometry APIs.
| Method | Purpose |
|---|---|
createFragmentInstance(fragmentFiber) | Create the fragment instance object when the fragment mounts |
updateFragmentInstanceFiber(fragmentFiber, instance) | Update the fiber pointer when the fragment re-renders |
commitNewChildToFragmentInstance(child, fragmentInstance) | Register a newly inserted child with the fragment |
deleteChildFromFragmentInstance(child, fragmentInstance) | Unregister a deleted child |
Renderers that don't support this return null from createFragmentInstance and use no-ops for the rest.
Sources: packages/react-native-renderer/src/ReactFiberConfigFabric.js832-870 packages/react-native-renderer/src/ReactFiberConfigNative.js208-235 packages/react-test-renderer/src/ReactFiberConfigTestHost.js477-504
A minimal third-party renderer using the public npm react-reconciler package must:
require('react-reconciler').supportsMutation: true (or supportsPersistence: true) and implement the corresponding methods.supportsPersistence: false, supportsHydration: false, etc. for any groups not implemented.The test in packages/react-reconciler/src/__tests__/ReactFiberHostContext-test.internal.js demonstrates the minimal interface required: it passes a flat object with prepareForCommit, resetAfterCommit, getRootHostContext, getChildHostContext, shouldSetTextContent, createInstance, finalizeInitialChildren, appendInitialChild, appendChildToContainer, clearContainer, setCurrentUpdatePriority, getCurrentUpdatePriority, resolveUpdatePriority, trackSchedulerEvent, resolveEventType, resolveEventTimeStamp, shouldAttemptEagerTransition, requestPostPaintCallback, suspensey commit methods, and supportsMutation: true.
Sources: packages/react-reconciler/src/__tests__/ReactFiberHostContext-test.internal.js37-121
Refresh this wiki