Registry / web-framework / react-reconciler

react-reconciler

JSON →
library0.33.0jsnpmunverified

react-reconciler is an experimental, low-level package provided by the React team for developers who wish to build custom React renderers for non-standard environments, such as WebGL, terminal UIs, or native desktop applications. It encapsulates the core reconciliation logic (the 'Fiber' architecture since React 16) responsible for efficiently diffing component trees and determining the minimal set of changes needed to update the UI. The package, currently at version 0.33.0, is designed to be pluggable with a custom `HostConfig` object, allowing developers to define platform-specific operations for creating, updating, and deleting nodes. Its API is explicitly unstable and does not adhere to React's standard versioning scheme, meaning breaking changes can occur in minor versions. It requires `react` as a peer dependency, specifically `>=19.2.0` for this version. It supports two primary modes: 'mutation mode' for environments that modify existing nodes (like the DOM) and 'persistent mode' for immutable tree structures.

npm install react-reconciler
INSTALL
IMPORT
SIG · REACT-RECONCILER
R
react-reconciler
web-frameworkjavascriptv0.33.0
Install
—
Import
—
Disk
—
Pass rate
0/ 6
Env Coverage0 / 6
glibc
18–22
musl
18–22
Install & Compatibility
Where this runs
tested against v? · npm install
Install × environment matrix
Each cell = how many times install + import succeeded across repeated harness runs. Partial = flaky.
glibc = Debian/Ubuntu slim · musl = Alpine Linux
musl
node 18–226 runs
build_error
glibc
node 18–226 runs
build_error
Code
Verified usage

Verified import paths — ran on the pinned version, not inferred.

createReconciler
✓ import Reconciler from 'react-reconciler';
✗ import { createReconciler } from 'react-reconciler';
The primary factory function is typically imported as the default export. Many examples name the imported value 'Reconciler' or 'createReconciler'. For CommonJS, use `const Reconciler = require('react-reconciler');`
DiscreteEventPriority, ContinuousEventPriority, DefaultEventPriority
✓ import { DiscreteEventPriority, ContinuousEventPriority, DefaultEventPriority } from 'react-reconciler/constants';
✗ import { DefaultEventPriority } from 'react-reconciler';
Event priority constants, crucial for implementing `getCurrentEventPriority` in `HostConfig`, are imported from a specific subpath.
HostConfig (interface/type)
✓ import type { HostConfig } from 'react-reconciler';
✗ import { HostConfig } from 'react-reconciler';
While `HostConfig` is a conceptual interface for configuring the renderer, it's not directly exported as a value for runtime import. It's a type definition; for actual implementation, you define an object conforming to it.

This example demonstrates how to create a basic custom React renderer using `react-reconciler`. It defines a minimal `HostConfig` for a 'console' environment, logs lifecycle events, and shows how to use `createContainer` and `updateContainer` to render a simple React component.

import React from 'react'; import Reconciler from 'react-reconciler'; // Minimal HostConfig for a 'console' renderer const hostConfig = { now: Date.now, supportsMutation: true, // Or supportsPersistence: true for immutable trees getRootHostContext: () => ({}), getChildHostContext: (parentHostContext, type) => parentHostContext, getPublicInstance: (instance) => instance, prepareForCommit: () => null, resetAfterCommit: () => {}, createInstance: (type, props, rootContainerInstance, hostContext, internalInstanceHandle) => { // In a real renderer, this would create a DOM node, canvas object, etc. const instance = { type, props, children: [] }; console.log(`CREATE: <${type}>`, props); return instance; }, createTextInstance: (text, rootContainerInstance, hostContext, internalInstanceHandle) => { console.log(`CREATE TEXT: "${text}"`); return text; }, appendInitialChild: (parentInstance, child) => { parentInstance.children.push(child); console.log(`APPEND INITIAL CHILD:`, { parent: parentInstance.type, child }); }, appendChild: (parentInstance, child) => { parentInstance.children.push(child); console.log(`APPEND CHILD:`, { parent: parentInstance.type, child }); }, insertBefore: (parentInstance, child, beforeChild) => { const index = parentInstance.children.indexOf(beforeChild); if (index > -1) { parentInstance.children.splice(index, 0, child); } console.log(`INSERT BEFORE:`, { parent: parentInstance.type, child, before: beforeChild }); }, removeChild: (parentInstance, child) => { parentInstance.children = parentInstance.children.filter(c => c !== child); console.log(`REMOVE CHILD:`, { parent: parentInstance.type, child }); }, prepareUpdate: (instance, type, oldProps, newProps, rootContainerInstance, hostContext) => { // Compare oldProps and newProps to determine what needs to change. const payload = {}; for (const key in newProps) { if (newProps[key] !== oldProps[key]) { payload[key] = newProps[key]; } } return Object.keys(payload).length > 0 ? payload : null; }, commitUpdate: (instance, updatePayload, type, oldProps, newProps, internalHandle) => { Object.assign(instance.props, updatePayload); console.log(`UPDATE: <${type}>`, updatePayload); }, commitTextUpdate: (textInstance, oldText, newText) => { console.log(`TEXT UPDATE: "${oldText}" -> "${newText}"`); Object.assign(textInstance, newText); // Assuming textInstance is mutable string or wrapper }, shouldSetTextContent: (type, props) => typeof props.children === 'string' || typeof props.children === 'number', // Add other required methods like scheduleTimeout, cancelTimeout, noTimeout, etc. scheduleTimeout: setTimeout, cancelTimeout: clearTimeout, noTimeout: -1, isPrimaryRenderer: true, getCurrentEventPriority: () => 3, // DefaultEventPriority (requires import from 'react-reconciler/constants') // A minimal set of methods is still quite large. Many can be no-ops initially. }; const MyRenderer = Reconciler(hostConfig); const rootContainer = {}; // Represents the 'host' root, e.g., a canvas element, a terminal object const root = MyRenderer.createContainer(rootContainer, false, false); // No hydrate, no hydrationCallbacks export function render(element, container) { // `container` here would be the root object in your host environment // like `document.getElementById('root')` for ReactDOM. // For this console example, we'll just use the `rootContainer` created above. MyRenderer.updateContainer(element, root, null, () => { console.log('RENDER COMPLETE!', rootContainer); // For a console renderer, you'd print the final tree here. // In a real app, this would trigger a flush of pending updates to the actual UI. }); } // Example usage function App() { const [count, setCount] = React.useState(0); React.useEffect(() => { const interval = setInterval(() => setCount(c => c + 1), 1000); return () => clearInterval(interval); }, []); return ( <box color="blue"> <text>{`Count: ${count}`}</text> <button onClick={() => setCount(0)}>Reset</button> </box> ); } render(<App />, rootContainer);
Debug
Known issues
breakingThe `react-reconciler` package is explicitly marked as experimental and unstable. Its API does not follow React's usual semantic versioning, and breaking changes can occur without major version bumps. Users should expect to adapt their custom renderers frequently.
fix
Always pin `react-reconciler` to an exact version and thoroughly test custom renderers after any updates. Monitor React's official GitHub repository for changes to the internal reconciler code.
affects: >=0.1.0
gotchaImplementing a complete and performant `HostConfig` is a highly complex task, requiring deep understanding of React's Fiber architecture and the target platform's rendering specifics. Missing or incorrectly implemented methods can lead to subtle bugs, memory leaks, or poor performance.
fix
Refer to existing open-source custom renderers (e.g., React Three Fiber, Ink) and the internal React DOM/Native host configs for comprehensive examples. Start with a minimal set of methods and incrementally add functionality, testing at each step.
affects: >=0.1.0
gotchaChoosing between `supportsMutation: true` and `supportsPersistence: true` in your `HostConfig` is critical. Incorrectly selecting the mode (e.g., mutation for an immutable tree) will lead to incorrect rendering, performance issues, and potential crashes.
fix
Understand your target platform's rendering model. If your environment modifies existing nodes (like the DOM), use `supportsMutation`. If it generates new immutable trees on every update, use `supportsPersistence`.
affects: >=0.1.0
gotchaThe peer dependency `react` must match the expected major version for `react-reconciler`. For version 0.33.0, this is `^19.2.0`. Mismatched React versions can lead to runtime errors or unexpected behavior due to internal API differences.
fix
Ensure your project's `react` dependency satisfies the peer dependency range of `react-reconciler`. Use `npm install --force` or `yarn add --force` with caution if necessary, but ideally resolve conflicts cleanly.
affects: >=0.33.0
Errors
Common errors & fixes
Error: This module must be shimmed by a specific renderer.
Attempting to import internal `ReactFiberConfig` directly or a similar internal React module that expects a renderer-specific shim.
fix
You should not be directly importing internal React modules like `ReactFiberConfig`. Instead, you define a `HostConfig` object and pass it to the `Reconciler` factory function.
Warning: Each child in a list should have a unique 'key' prop.
While a general React warning, it's critical for custom renderers as it directly impacts the reconciliation algorithm's performance when diffing lists of elements. Using array indices as keys for dynamic lists is a common cause.
fix
Always provide a stable, unique `key` prop for each item in a list. This key should ideally come from the data itself, not the array index, especially if the list can be reordered, filtered, or grow.
UI doesn't update or renders inconsistently after state changes.
In a custom renderer, this often means `updateContainer` is not called correctly after state changes, or the `HostConfig` methods (e.g., `commitUpdate`, `commitTextUpdate`, `appendChild`, `removeChild`) are not implemented to correctly apply changes to the host environment.
fix
Verify that `MyRenderer.updateContainer(element, root, null, callback)` is invoked whenever the root element changes. Debug your `HostConfig` methods to ensure they correctly translate React's instructions into operations on your host environment's instances.
Upgrade
Version history
0.33.0latest on npm
Audit
Dependencies
reactrequiredCore React library for defining components and elements. react-reconciler operates on React elements.
Agent activity
2 hits · last 30 days
node
2
Resources
react-reconciler — npm install react-reconciler · libregistry