Appearance
Canvas
FreshThe Canvas object is where you start to define your React Three Fiber scene.
jsx
import React from 'react'
import { Canvas } from '@react-three/fiber'
const App = () => (
<Canvas>
<pointLight position={[10, 10, 10]} />
<mesh>
<sphereGeometry />
<meshStandardMaterial color="hotpink" />
</mesh>
</Canvas>
)Properties
| Prop | Description | Default |
|---|---|---|
children | three.js JSX elements or regular components | |
fallback | optional DOM JSX elements in case GL is not supported | |
gl | Props for the default renderer. Accepts sync/async callback gl={defaults => new Renderer({ ...defaults })} | {} |
camera | Props for the default camera, or your own THREE.Camera | { fov: 75, near: 0.1, far: 1000, position: [0, 0, 5] } |
scene | Props for the default scene, or your own THREE.Scene | {} |
shadows | Props for gl.shadowMap, can be set true for PCFsoft or: 'basic', 'percentage', 'soft', 'variance' | false |
raycaster | Props for the default raycaster | {} |
frameloop | Render mode: always, demand, never | always |
resize | Resize config, see react-use-measure's options | { scroll: true, debounce: { scroll: 50, resize: 0 } } |
orthographic | Creates an orthographic camera | false |
dpr | Pixel-ratio, use window.devicePixelRatio, or automatic: [min, max] | [1, 2] |
legacy | Enables THREE.ColorManagement in three r139 or later | false |
linear | Switch off automatic sRGB color space and gamma correction | false |
events | Configuration for the event manager, as a function of state | import { events } from "@react-three/fiber" |
eventSource | The source where events are being subscribed to, HTMLElement | gl.domElement.parentNode |
eventPrefix | The event prefix cast into canvas pointer x/y events | offset |
flat | Use THREE.NoToneMapping instead of THREE.ACESFilmicToneMapping | false |
onCreated | Callback after the canvas has rendered (but not yet committed) | (state) => {} |
onPointerMissed | Response for pointer clicks that have missed any target | (event) => {} |
Defaults
Canvas uses createRoot which will create a translucent THREE.WebGLRenderer with the following constructor args:
antialias=truealpha=truepowerPreference="high-performance"
And with the following properties:
outputColorSpace = THREE.SRGBColorSpacetoneMapping = THREE.ACESFilmicToneMapping
It will also create the following scene internals:
- A
THREE.Perspectivecamera - A
THREE.Orthographiccam iforthographicis true - A
THREE.PCFSoftShadowMapifshadowsis true - A
THREE.Scene(into which all the JSX is rendered) and aTHREE.Raycaster
In recent versions of three.js, THREE.ColorManagement.enabled will be set to true to enable automatic conversion of colors according to the renderer's configured color space. R3F will handle texture color space conversion.
Errors and Fallbacks
On some systems WebGL may not be supported. Provide a fallback component:
jsx
<Canvas fallback={<div>Sorry no WebGL supported!</div>}>
<mesh />
</Canvas>Safeguard against WebGL context crashes with an error boundary:
jsx
import { useErrorBoundary } from 'use-error-boundary'
function App() {
const { ErrorBoundary, didCatch, error } = useErrorBoundary()
return didCatch ? (
<div>{error.message}</div>
) : (
<ErrorBoundary>
<Canvas>
<mesh />
</Canvas>
</ErrorBoundary>
)
}WebGPU
Recent three.js includes a WebGPU renderer. R3F supports it via an async gl prop:
tsx
import * as THREE from 'three/webgpu'
import * as TSL from 'three/tsl'
import { Canvas, extend, useFrame, useThree } from '@react-three/fiber'
declare module '@react-three/fiber' {
interface ThreeElements extends ThreeToJSXElements<typeof THREE> {}
}
extend(THREE as any)
export default () => (
<Canvas
gl={async (props) => {
const renderer = new THREE.WebGPURenderer(props as any)
await renderer.init()
return renderer
}}>
<mesh>
<meshBasicNodeMaterial />
<boxGeometry />
</mesh>
</Canvas>
)Custom Canvas with createRoot
R3F can render to a root directly, allowing you to shave off react-dom (~40kb), react-use-measure (~3kb), and pointer events (~7kb).
jsx
import * as THREE from 'three'
import { extend, createRoot, events } from '@react-three/fiber'
// Register the THREE namespace as native JSX elements
extend(THREE)
// Create a react root
const root = createRoot(document.querySelector('canvas'))
async function app() {
// Configure the root — must be called before render, must be awaited
await root.configure({ events, camera: { position: [0, 0, 50] } })
// createRoot is not responsive — handle resize yourself
window.addEventListener('resize', () => {
root.configure({ size: { width: window.innerWidth, height: window.innerHeight } })
})
window.dispatchEvent(new Event('resize'))
root.render(<App />)
// Unmount and dispose of memory
// root.unmount()
}
app()Tree-Shaking
New with v8, the underlying reconciler no longer pulls in the THREE namespace automatically. This enables tree-shaking via the extend API:
jsx
import { extend, createRoot } from '@react-three/fiber'
import { Mesh, BoxGeometry, MeshStandardMaterial } from 'three'
extend({ Mesh, BoxGeometry, MeshStandardMaterial })
createRoot(canvas).render(
<>
<mesh>
<boxGeometry />
<meshStandardMaterial />
</mesh>
</>,
)