API

Babylon.js and React

How to use Babylon.js with React

For anyone interested, it is not difficult to integrate Babylon.js into a React application.

What you need

It's up to you whether you choose Create React App or a custom project; this guide only discusses how to load Babylon.js in a component. This example uses the newer @babylonjs/core ES6 NPM package, but it can also be modified to work with the babylonjs NPM package.

Component

We are going to build a reusable React component that takes care of starting up Babylon.js for us!

In a working React project you first need to install the package @babylonjs/core using npm or yarn:

npm install @babylonjs/core
yarn add @babylonjs/core

Create a file called SceneComponent.jsx and add this:

import { useEffect, useRef } from "react";
import { Engine, Scene } from "@babylonjs/core";
export default ({ antialias, engineOptions, adaptToDeviceRatio, sceneOptions, onRender, onSceneReady, ...rest }) => {
const reactCanvas = useRef(null);
// set up basic engine and scene
useEffect(() => {
const { current: canvas } = reactCanvas;
if (!canvas) return;
const engine = new Engine(canvas, antialias, engineOptions, adaptToDeviceRatio);
const scene = new Scene(engine, sceneOptions);
if (scene.isReady()) {
onSceneReady(scene);
} else {
scene.onReadyObservable.addOnce((scene) => onSceneReady(scene));
}
engine.runRenderLoop(() => {
if (typeof onRender === "function") onRender(scene);
scene.render();
});
const resize = () => {
scene.getEngine().resize();
};
if (window) {
window.addEventListener("resize", resize);
}
return () => {
scene.getEngine().dispose();
if (window) {
window.removeEventListener("resize", resize);
}
};
}, [antialias, engineOptions, adaptToDeviceRatio, sceneOptions, onRender, onSceneReady]);
return <canvas ref={reactCanvas} {...rest} />;
};

In 45 lines we have:

  • Reusable React Component for Babylon.js.
  • Will resize the engine when window is resized.
  • Cleans up resources automatically when unmounted.
  • Any extra props you add to this component will flow to the canvas (i.e. style/className).
  • We only need to add this component to a page and specify a method to run when the scene is ready. A <canvas /> element is created and a Babylon.js engine and scene are created and started.
  • If you want more control of the runRenderLoop, just remove it from here and add it in your onSceneReady prop.
  • TypeScript source can be copied from here.

The above component is available on npm, if you prefer:

npm add babylonjs-hook
yarn add babylonjs-hook

Here is a page using our component:

import React from "react";
import { FreeCamera, Vector3, HemisphericLight, MeshBuilder } from "@babylonjs/core";
import SceneComponent from "./SceneComponent"; // uses above component in same directory
// import SceneComponent from 'babylonjs-hook'; // if you install 'babylonjs-hook' NPM.
import "./App.css";
let box;
const onSceneReady = (scene) => {
// This creates and positions a free camera (non-mesh)
const camera = new FreeCamera("camera1", new Vector3(0, 5, -10), scene);
// This targets the camera to scene origin
camera.setTarget(Vector3.Zero());
const canvas = scene.getEngine().getRenderingCanvas();
// This attaches the camera to the canvas
camera.attachControl(canvas, true);
// This creates a light, aiming 0,1,0 - to the sky (non-mesh)
const light = new HemisphericLight("light", new Vector3(0, 1, 0), scene);
// Default intensity is 1. Let's dim the light a small amount
light.intensity = 0.7;
// Our built-in 'box' shape.
box = MeshBuilder.CreateBox("box", { size: 2 }, scene);
// Move the box upward 1/2 its height
box.position.y = 1;
// Our built-in 'ground' shape.
MeshBuilder.CreateGround("ground", { width: 6, height: 6 }, scene);
};
/**
* Will run on every frame render. We are spinning the box on y-axis.
*/
const onRender = (scene) => {
if (box !== undefined) {
const deltaTimeInMillis = scene.getEngine().getDeltaTime();
const rpm = 10;
box.rotation.y += (rpm / 60) * Math.PI * 2 * (deltaTimeInMillis / 1000);
}
};
export default () => (
<div>
<SceneComponent antialias onSceneReady={onSceneReady} onRender={onRender} id="my-canvas" />
</div>
);

A few notes on the code

This will show the basic playground on your website! A rotation has been added in the render loop (and the sphere has been changed to a box, so you can notice it).

If you would like to see this in action, there is a boilerplate project using the original babylonjs NPM package, which you can clone from:

There is a boilerplate using the above component with the ES6 NPM package @babylonjs/core here:

Adding other Babylon.js NPMs

If you start with the @babylonjs ES6 NPMs (as we have done), then add only those packages.

For GUI use @babylonjs/gui instead of the NPMs that don't start with @.

Conclusion

Integrating Babylon.js into a React site turns out to be not so difficult. Since Babylon.js 3.1, we can use ES6 imports not only for Babylon.js, but also for supported libraries (GUI/loaders/etc.).

If the component above does everything you need, then that's all you need and you're all set! If you want to take it a step further, you may want to take the react-babylonjs renderer for a spin.

react-babylonjs renderer

A renderer is a next-level React integration that lets you use JSX to build your scenes and GUI. State changes will flow automatically to your Babylon.js components (and persist through HMR), and you can maintain your scene graph with declarative syntax and components.

There is an NPM project called react-babylonjs that is a React renderer for Babylon.js.

What you are able to easily do is powerful, because inside the Scene component you can declare Babylon.js objects like Cameras/Meshes/Lights/Materials/Textures/3D Models/etc, using familiar JSX. Meanwhile there are escape hatches that allow you to work imperatively as well.

Babylon.js ES6 + CRA (Create React App) project examples:

  • JavaScript (examples for 3D models, GUI, VR, behaviors, props/state management)
  • TypeScript (GUI + physics + shadows)
  • Electron (Electron added to above TypeScript project)
  • PWA (Progressive Web App)

react-babylonjs (https://github.com/brianzinn/react-babylonjs) links to many live storybook code examples (skybox, CSG, dynamic terrain, behaviors, GUI, react hooks, integrations (PIXI, react-spring, gsap, chroma-js), 3D models, physics, shadows, layers (glow/highlight), textures, fresnel parameters, PBR, etc.