babylon-lite-hook
v0.0.2
Published
React hooks and Suspense-ready scene component for Babylon Lite (@babylonjs/lite)
Maintainers
Readme
babylon-lite-hook
React hooks and a Suspense-ready <SceneComponent> for Babylon Lite (@babylonjs/lite) — the WebGPU-first, tree-shakable renderer from the Babylon.js team.
This is the babylonjs-hook you already know, ported to Babylon Lite. The JSX is intentionally the same — in most cases you change the library you import scene-building functions from and everything else keeps working. Because Babylon Lite's setup is genuinely async (createEngine, registerScene, startEngine and asset loading all return Promises), the component integrates with React Suspense: pass a fallback and it renders while the engine, your scene setup and the first frame complete.
Requirements
- React 19+ (uses the
useAPI for Suspense) @babylonjs/lite1.8+- A WebGPU-capable browser — Babylon Lite is WebGPU-exclusive by design (no WebGL fallback)
How to Install
npm i babylon-lite-hook @babylonjs/liteBasic Usage
import React from 'react';
import {
addToScene,
attachFreeControl,
createBox,
createFreeCamera,
createGround,
createHemisphericLight,
} from '@babylonjs/lite';
import SceneComponent from 'babylon-lite-hook';
import './App.css';
let box;
const onSceneReady = (scene) => {
// This creates and positions a free camera (plain data — no methods)
const camera = createFreeCamera({ x: 0, y: 5, z: -10 }, { x: 0, y: 0, z: 0 });
scene.camera = camera;
// This attaches the camera to the canvas
attachFreeControl(camera, scene.surface.canvas, scene);
const engine = scene.surface.engine;
// This creates a light, aiming 0,1,0 - to the sky
addToScene(scene, createHemisphericLight([0, 1, 0], 0.7));
// Our built-in 'box' shape.
box = createBox(engine, 2);
// Move the box upward 1/2 its height
box.position.y = 1;
addToScene(scene, box);
// Our built-in 'ground' shape.
addToScene(scene, createGround(engine, { width: 6, height: 6 }));
};
/**
* Will run on every frame render. We are spinning the box on y-axis.
*/
const onRender = (scene, deltaMs) => {
if (box !== undefined) {
const rpm = 10;
box.rotation.y += (rpm / 60) * Math.PI * 2 * (deltaMs / 1000);
}
};
function App() {
return (
<div className="App">
<header className="App-header">
<SceneComponent
antialias
onSceneReady={onSceneReady}
onRender={onRender}
id="my-canvas"
fallback={<div>loading…</div>}
/>
</header>
</div>
);
}
export default App;Suspense
Everything between "canvas mounted" and "first frame rendered" is one Suspense window: engine creation, your onSceneReady (which may be async — load glTF models, environments, …), scene registration and the first rendered frame. While that's pending, the fallback renders; the canvas itself stays mounted the whole time (Babylon Lite needs it), so style the fallback as an overlay if you want a loading screen on top of the canvas.
const onSceneReady = async (scene) => {
const engine = scene.surface.engine;
scene.camera = createDefaultCamera(scene);
// the component suspends until this resolves — no loading-state bookkeeping needed
addToScene(scene, await loadGltf(engine, 'model.glb'));
};
<SceneComponent onSceneReady={onSceneReady} fallback={<LoadingOverlay />}>
<SceneUI />
</SceneComponent>;Children render only once the scene is ready, so useScene() / useEngine() inside them never return null in practice. Initialization failures (e.g. no WebGPU support) propagate to the nearest error boundary:
<ErrorBoundary fallback={<p>This experience needs a WebGPU-capable browser.</p>}>
<SceneComponent onSceneReady={onSceneReady} fallback={<LoadingOverlay />} />
</ErrorBoundary>Hooks
| hook | description |
| ---------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------- |
| useScene() | The Babylon Lite SceneContext (or null outside a ready <SceneComponent>). |
| useEngine() | The EngineContext. Also reachable as scene.surface.engine. |
| useCanvas() | The rendering HTMLCanvasElement. |
| useBeforeRender(cb) | Registers cb(scene, deltaMs) before each frame; auto-unregisters on unmount. |
| useCamera(createCameraFn, autoAttach?) | Creates a camera, assigns scene.camera and (by default) attaches pointer controls for ArcRotate/Free cameras — detached and cleared on unmount. |
const SpinningLabel = () => {
const scene = useScene();
useCamera((scene) => createArcRotateCamera(-Math.PI / 2, Math.PI / 2.5, 8, { x: 0, y: 0, z: 0 }));
useBeforeRender((scene, deltaMs) => {
// per-frame logic
});
return null;
};Porting from babylonjs-hook
The JSX shape is unchanged — swap the import and port onSceneReady to Babylon Lite's function-based API (see the porting guide).
| babylonjs-hook | babylon-lite-hook |
| ----------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------- |
| onSceneReady(scene) | Same prop, now optional and may be async — the component suspends until it resolves. |
| onRender(scene) | Same prop, with the frame delta as a bonus second argument: onRender(scene, deltaMs). |
| antialias | Same prop — maps to msaaSamples: 4 / 1 (Lite defaults to 4x MSAA). |
| adaptToDeviceRatio | Same prop — Lite adapts by default; false maps to maxDevicePixelRatio: 1. |
| engineOptions / sceneOptions | Same props — Lite's EngineOptions / SceneContextOptions. |
| renderChildrenWhenReady | Superseded by Suspense: children always render when the scene is ready. Prop is accepted but ignored. |
| observeCanvasResize | Not needed: Lite resizes the engine from the canvas layout every frame. Prop is accepted but ignored. |
| useBeforeRender(cb, mask?, insertFirst?, callOnce?) | useBeforeRender(cb) — Lite has no observable masks; cb receives (scene, deltaMs). |
| useAfterRender(cb) | Not available — Babylon Lite has no after-render hook. Open an issue if you need it. |
| useCamera(fn, autoAttach?, noPreventDefault?) | useCamera(fn, autoAttach?) — attach/detach is handled through Lite's attachControl/attachFreeControl. |
| SceneContext (React context) | Renamed to SceneReactContext to avoid clashing with @babylonjs/lite's SceneContext type. The useScene() hook is unchanged. |
| withEngineCanvasContext HOC | Removed — use the useEngine() / useCanvas() hooks. |
Related
- react-babylonjs — full React renderer for (classic) Babylon.js
- babylonjs-hook — this package's predecessor, for
@babylonjs/core
Made with ♥ by Brian Zinn
