Course outline
Why React Three Fiber
In one line
R3F writes the same three.js objects as JSX and keeps them in step with React state. It does not wrap or hide three.js: every tag is a real three.js class, and the version rule is fiber 9 with React 19.
Think of it like this
An architect's drawing and a builder. You hand the builder a drawing ("a wall here, a window there") and say what changed in the new version. The builder works out what to build, move or knock down. JSX is the drawing, R3F is the builder, and three.js is the building.
Words you'll meet
New words in this topic, in plain English. Come back here whenever one feels fuzzy.
- renderer (React)
- A program that takes React components and builds something other than web page elements from them.
react-dombuilds HTML; R3F builds three.js objects. - JSX
- The tag-like syntax React uses to describe what to build, such as
<mesh />. A build tool turns it into plain function calls. - Canvas
- R3F's root component. It creates the renderer, the scene and the camera, and everything inside it becomes three.js objects.
- args
- A prop holding the list of arguments for a class's constructor.
args={[1, 2, 3]}isnew Box(1, 2, 3). - drei
- The helper library for R3F (German for "three"). It holds ready-made controls, loaders and effects.
Step by step
01One tag, one class
<mesh name="cube"> creates a THREE.Mesh and sets mesh.name = "cube". Its two children attach themselves to it: the geometry tag fills mesh.geometry, the material tag fills mesh.material. Nothing is drawn yet.
02The Canvas builds the world
<Canvas> makes a WebGLRenderer, a Scene and a PerspectiveCamera, and starts a loop. Its camera prop is applied to the default camera (position: [0, 0, 3]). onCreated runs once the world exists and gives you scene, gl and camera.
03Hooks reach the live objects
useFrame((state, delta) => ...) runs a function before each draw. ref.current is the real THREE.Mesh, so ref.current.rotation.y += delta is exactly the three.js you already know.
04Read the defaults
The second example prints what <Canvas> chose. The flat prop turns tone mapping off. Compare the two balls: the same material gets a different brightness and saturation, because tone mapping remaps bright colours (Topic 5.6).
Try it yourself
- 1
Add a second mesh
In the first example, add
<mesh position-x={1}><boxGeometry /></mesh>next to<Cube />. The output becomesobjects in the scene: 2 | Mesh cube. The new mesh has no material tag, so three.js gives it a default one. - 2
Remove flat
In the second example, delete
flat. The right ball now matches the left one, and the second report line saysACESFilmicToneMapping. R3F sets tone mapping unless you passflator setgl={{ toneMapping }}yourself (the build topic does).
Code & diagrams
The first line is R3F's own clock warning (explained above). The scene holds one object: the Cube component's mesh.
Console
Run the scene to see its console.Expected console output
THREE.Clock: This module has been deprecated. Please use THREE.Timer instead.
objects in the scene: 1 | Mesh cubeTwo Canvases, so the warning appears twice. Left: the defaults. Right: `flat`. Compare the colour of the two balls.
Console
Run the scene to see its console.Expected console output
THREE.Clock: This module has been deprecated. Please use THREE.Timer instead.
default: WebGLRenderer | camera PerspectiveCamera fov 75 at 0,0,5
default: tone mapping ACESFilmicToneMapping | output srgb | scene.background null
THREE.Clock: This module has been deprecated. Please use THREE.Timer instead.
flat: WebGLRenderer | camera PerspectiveCamera fov 75 at 0,0,5
flat: tone mapping NoToneMapping | output srgb | scene.background nullBreak it on purpose
Errors are the best teachers. Make each change, read the error, guess what went wrong, then reveal the answer.
Break #1
Forget the Canvas
Render <mesh><boxGeometry /></mesh> straight into createRoot(...), with no <Canvas>.
Myth vs fact
Myth
R3F is a different engine, so it renders differently or slower.
Fact
It calls the same three.js. The numbers in the status bar are the same as for hand-written code. Only React's own work (re-rendering components) is extra.
Myth
You have to learn new names for everything.
Fact
The names are three.js class names with a lowercase first letter, and the props are the class's properties. If you know MeshStandardMaterial({ roughness }), you know <meshStandardMaterial roughness={...} />.
Pro corner
Extra depth for experienced readers. New to this? Skip it for now and come back later.
- ▸
R3F is a custom React reconciler (the same mechanism as
react-dom). When state changes, React works out which tags changed and R3F applies only those changes to the three.js objects. It never rebuilds the scene. - ▸
Canvasgives every R3F tree its own React root and its own WebGL context. Two Canvases are two contexts (Chromium keeps at most 16 per page), and React context from outside the Canvas does not cross into it. Re-provide any context you need inside. - ▸
The default
dpris[1, 2]: pixel ratio is the device's, but never above 2. On a phone at ratio 3 that already saves more than half the pixels (Topic 1.1).
Remember this
- 1
The problem this solves: a page has buttons, lists and prices (UI) and a 3D scene. In plain three.js the two live in different worlds: you write listeners that reach into the scene, and keep state in both. In R3F the scene is part of the component tree, so one piece of state can drive both.
- 2
What a tag is.
<mesh>meansnew THREE.Mesh().<boxGeometry args={[1, 1, 1]} />meansnew THREE.BoxGeometry(1, 1, 1), attached to its parent asgeometry. The name is the class name with a lowercase first letter. R3F reads the list of classes from the installed three.js, so every class is available, including ones you write yourself. - 3
What R3F does for you. It makes the renderer, the scene and a camera, sizes the canvas to its parent, sets the pixel ratio (between 1 and 2 by default), runs the render loop, finds clicks with a raycaster (Phase 8), and creates and
dispose()s objects as components mount and unmount. In the second example you can read the defaults it chose: a perspective camera with field of view 75 at z = 5, ACES tone mapping and sRGB output. - 4
What R3F does not do. It is not a new engine and it is not slower by itself: the draw calls, triangles and memory are exactly the same as the equivalent three.js. Geometry cost, material count and texture size (Phase 17) are still your job. The only extra cost is React's work when state changes, which Topic 11.3 shows how to avoid.
- 5
The version rule.
@react-three/fiber9 needs React 19 (fiber 8 is for React 18). The course pins@react-three/fiber9.8.2,@react-three/drei10.7.9,react19.2.8 andthree0.186.1. Mismatched versions are the most common cause of strange install errors, so pin them as the build topic does. - 6
When plain three.js is the better choice. A page with no React, a scene with almost no UI, or code that must run in a worker or a non-React app: use three.js directly. R3F also does not help with a tight custom render loop. For a product page that already uses React, it usually removes code.
- 7
The Clock warning. With three r186, R3F 9.8.2 prints
THREE.Clock: This module has been deprecated. Please use THREE.Timer instead.once for every Canvas. It comes from R3F's own clock, not from your code. Nothing is broken, and you cannot silence it by editing your scene. It will go away in a later R3F release that usesTHREE.Timer; until then, expect to see it as the first line in every R3F example on this page.
Explain it without notes
What does <mesh><boxGeometry args={[1, 1, 1]} /></mesh> create, and how do the two tags find each other?
A teammate says R3F will make the 3D scene slow because it adds a layer. What is true and what is not?
Practice
Write the JSX for a mesh named wheel at x = 0.58, y = 0.35: a TorusGeometry with radius 0.33 and tube 0.022, in dark grey #22262c rubber with roughness 0.9.
Install the packages for an R3F project with exact versions, and say which two version numbers must go together.
Trade-offs
- ↔
R3F is shorter and shares state with the UI, but it adds React and the reconciler to your bundle, and a team must know React well. For a page with no React, plain three.js is simpler.
Done when you can
Say what a JSX tag creates and how a child tag attaches to its parent
Say what Canvas builds for you and read its defaults
State the version rule: fiber 9 with React 19
Explain the Clock warning and why it is harmless