Skip to main content

<ThreeDom /> Component

The main bridge component. Place it inside your R3F <Canvas>.

import { Canvas } from '@react-three/fiber';
import { ThreeDom } from '@react-three-dom/core';

<Canvas>
<ThreeDom />
{/* your scene */}
</Canvas>

Props​

PropTypeDefaultDescription
canvasIdstring—Unique ID for multi-canvas apps. Registers in window.__R3F_DOM_INSTANCES__[canvasId].
primarybooleantrue when no canvasIdWhether window.__R3F_DOM__ points to this instance.
mode"auto" | "manual""auto"auto registers all objects. manual requires explicit registration via useR3FRegister or r3fRegister().
filter(obj: Object3D) => boolean—Only register objects that pass the filter. Auto mode only.
rootstring | HTMLElement"#three-dom-root"CSS selector or element for the mirror DOM container.
batchSizenumber500Objects to sync per amortized batch per frame.
syncBudgetMsnumber0.5Max time (ms) for sync work per frame.
maxDomNodesnumber2000Max materialized DOM nodes. LRU eviction when exceeded.
initialDepthnumber3How deep to materialize the DOM tree on mount.
enabledbooleantrueMaster switch for all sync.
debugbooleanfalseEnable debug logging to browser console.
inspectbooleanfalseEnable inspect mode on mount (hover-to-highlight).

Registration Modes​

Auto (default)​

Traverses the entire scene and registers every object. New objects added to the scene are automatically picked up via the Object3D.add patch.

<ThreeDom />

Auto with Filter​

Only objects that pass the filter are registered. Useful when you want to exclude lights, helpers, or internal objects from the mirror DOM.

<ThreeDom filter={(obj) => obj.type === 'Mesh' || obj.type === 'Group'} />

Manual​

Nothing is auto-registered. You control exactly which objects appear in the mirror DOM using the useR3FRegister hook or the r3fRegister() API.

<ThreeDom mode="manual" />

useR3FRegister Hook​

Registers a Three.js object on mount and unregisters on unmount. Works in both modes.

import { useR3FRegister } from '@react-three-dom/core';

function Wall({ geometry }) {
const ref = useRef<Mesh>(null!);
useR3FRegister(ref);
return <mesh ref={ref} geometry={geometry} userData={{ testId: 'wall' }} />;
}

For multi-canvas setups, pass the canvas ID:

useR3FRegister(ref, 'viewer2');

The hook automatically:

  • Retries if the bridge isn't ready yet on mount
  • Detects ref.current identity swaps and re-registers
  • Skips unregistration for auto-registered objects (won't accidentally remove them)

Error Handling​

If WebGL is unavailable or setup fails, the bridge creates a stub with _ready: false and an _error message. All API methods become no-ops. This prevents silent hangs — test waiters will see the error and fail with a clear message.