
To begin, we should ensure that we've set up an IDE (Integrated Development Environment) to develop with.
VSCode
The IDE that I will use is VSCode. If you also use VSCode then what you will see, will more closely match what I show in the videos.
If you don't have VSCode already installed, then you can install it.
Also, it is useful, but not essential, to be able to start VSCode from the command line.
We can check it is available from the command line by typing
code -v
The response should indicate a version number, plus several other bits of information.
Node.js
We also need Node.js, which includes NPM, since we will be using the npm and npx commands.
To check if Node.js is already installed, open a cmd/terminal/shell prompt and type,
node -v
You should get a response indicating a version number.
E.g.,
v16.13.2
Your version should be equal to or higher than v16.0.0.
We can also check the version of NPM,
npm -v
You want to see no error, but instead a version number equal to, or higher than v8.0.0.
E.g.,
8.19.2
If either of those two commands returned an error indicating that they were unrecognized, or the versions numbers were lower than required, then you can install the latest LTS (long term support) version of Node.js.
Git
You may also want to use Git, but it is not essential yet.
You can check if Git is already installed. It usually is, by default on Linux and macOS.
git --version
You want to see a version number higher than 2.0.0, and no error indicating that the command was unrecognized.
We will now build a bare minimum React Three Fiber boilerplate that we will use to start the course.
The boilerplate is almost the absolute minimum that you need to get React Three Fiber to display a Three.js scene. We will make many additions to the boilerplate as the course progresses.
We will begin to componentize elements of our basic template so that we become more confident in restructuring our applications.
We can convert the Canvas and the mesh from our JSX into their own components.
We will convert the mesh into a component first.
Props (a.k.a. properties) are used in React to pass in attributes to your components when you declare them in the JSX.
Our Box from the last lesson is our component that returns a JSX.Element describing a THREE.Mesh.
But we cannot modify any of its properties when we create it, so if we create 2 or more, then they will just be placed in the scene on top of each other in the same position.
Instead, we can add props that we will use to further initialize them with a position when we declare them in the JSX.
If you want to read or modify the properties of a component instance at run time, then it is beneficial to have some kind of reference to that instance.
In this example, I get a reference to each of the Box component instances, which are actually each a THREE.Mesh under the hood and log them to the console.
I will use the React useRef hook.
const instanceRef = useRef(initialValue)
The initial value, if not set, will be undefined until it is initialized when the JSX is rendered.
You have the option to set an initialValue. E.g., {}, [], or 1, or any value or object you need it to be, to act as a default until the reference is finally initialized.
In the last example, there was a very subtle error which you might not have picked up if I didn't bring it to your attention.
When I used console.log(ref) in the last example, the mesh hadn't actually finished being created in Three.js scene yet. So, if we needed to do any logic on that data within our script, then we would have needed to make sure that it actually existed first, otherwise ref.current would have been still undefined. This is because we tried to access ref and more specifically, it's current property, before it had been set when the JSX was converted into a Three.js object.
A way to improve on my last example would be to use the React useEffect hook.
The useFrame hook is a React Three Fiber hook and is useful if you want to execute code before every rendered frame.
In this example we will transform the mesh's rotation.
When React calls our useFrame hook, it gives us a state object of the Three.js scene, and a clock delta indicating how many milliseconds since the last time the delta was set. The delta time shows the milliseconds between renders and can be used to change an object over time at a consistent speed independent of the clients frame rate.
E.g., you could move an object at a speed of 10 units per second.
ref.current.position.x += 10 * delta
The useFrame hook will be invoked after the JSX is converted into Three.js objects and just before the current frame is rendered to the canvas.
The useFrame hook is invoked continually, and on desktop, will try to maintain a rate of 60 frames per second.
Our 3D objects can respond to pointer events and if anytime their props or state was changed.
In this example we can see that our boxes respond to events indicating when your pointer is down, up, over and out. The information is logged to the console.
There are many events that you add to your Threejs objects, See the list on the official documentation.
Note that when we capture an event, a lot of information about the event is passed into the callback. Example, if an object was clicked, then we can get information about that object, the 3D vector where the click occurred, the distance from the camera of the click, which face of the object was clicked, the UV coordinate of the click, and many things.
The pointer events rely on a raycaster that is automatically created when the React Three Fiber Canvas is instantiated.
Since the information about the event is passed into the callback, we don't need to create any dedicated useRef hook for our object to read that data. All the required information referencing our object is present in case we want to use that data or inspect it further in the console.
The useState Hook is a React component that allows us to track state between function calls and provide a way to modify it.
useState accepts an initial state and returns two values:
The current state.
A function that updates the state.
We should never directly update state in our components but use the useState hook instead.
In this section, I will show alternate ways of setting the geometry of our mesh using React and JSX.
By using these alternate methods, we need to consider how React will manage the objects within memory and the scene.
In this lesson, instead of using useMemo to cache our objects in the components for re-use, we can move the instances into the parent component, and then pass them down by reference. This will also allow us to re-use the same instances in the child components, rather than creating new copies of each.
Ok, we have done a lot about the fundamentals of understanding React and some React Three Fiber. Each of those concepts we've learned so far will get more involved, but now it's time to start adding more Three.js functionality to our scene since we are now ready to expand on the basics of Three.js.
The first component, which is a very useful tool when developing Three.js applications, is the Stats panel. It will show us by default, the frame rate that our application is achieving. On desktop, this is likely to be 60 frames per second. In VR, you may see 90-120 frames a second depending on the device. Ideally you want to keep that performance for your desktop/device when you gradually add new functionality to your application.
By using the Stats panel, you can see quickly when you've made a change, whether you should consider optimizing it, or trying a different approach.
Let's add another Three.js module, but again via a Drei import. The OrbitControls.
The axesHelper is an object to help visualize the 3 axes in a simple way. The X axis is red, the Y axis is green, and the Z axis is blue.
The axesHelper is part of the Three.js core library, and also included by default as part of the Threejs intrinsic elements that are referenced when using the React Three Fiber canvas.
The gridHelper is a two-dimensional grid of intersecting lines. It is useful if you need to imagine where a floor might be, or some other boundary.
Leva is a GUI component that you can add to your React Three Fiber application and interact with your scene.
In this lesson, we will introduce four of the most commonly used materials that you will see used in Three.js.
MeshBasicMaterial
MeshNormalMaterial
MeshPhongMaterial
MeshStandardMaterial
There are other materials, but we will discuss those, plus more details, about each material as we progress.
In this lesson, we will start by focusing on several important factors about materials and why you might choose to use them over others.
Let's add a few different types of lights to the scene and see how they affect the different materials.
Let's now add some shadows and see how different materials react.
The useLoader hook is used in React Three Fiber to pre-cache any assets in memory, such as images or 3D models for later use in the scene.
The useLoader hook, uses any Three.js loader module as its first argument. In this example, we will pass it the THREE.TextureLoader module. This will be used to texture our icosahedrons rather than using a single color as we've seen so far.
We can also load pre-built 3D models into our scene. In this example, I will use the useLoader hook to load a glTF model, by passing the Threejs GLTFloader module into the useLoader.
The glTF format,
is a specification for the efficient transmission and loading of 3D scenes and models.
Minimizes both the size of 3D assets, and the runtime processing needed to unpack and use those assets.
The exported asset may contain one or more scenes, meshes, materials, textures, skins, skeletons, morph targets, animations, lights and cameras.
Assets can be provided in either JSON (.gltf) or binary (.glb) format. Textures encoded in a .gltf JSON file are encoded using Base64, which can increase the payload by about 33%. So, prefer to use the .glb binary export option.
In this lesson, we will use Blender to quickly create a 3d model, export it as binary glTF file and view it in our Three.js scene.
We will also experiment with some Blender material settings and see how they translate into the Three.js scene.
We can make 3D models look much better if we set an environment map that it will use for any reflection calculations.
We can set the scene.environment property to a texture.
But since we are using React Three Fiber and Drei, we will use the Environment helper which produces a great effect and is much easier to use.
With this example, we will improve on our knowledge of Blender, Leva, importing models, the Object3D hierarchy, Environment and introduce the Drei ContactShadows.
The glTF specification provides a way to describe whole scenes which may include a large hierarchy of other 3D objects, as well as lighting, animations, materials, textures, skeletons, morph targets, cameras and even other scenes.
This means that you can create almost your whole scene using a 3D modelling tool such a Blender and import it into the Three.js scene with much less work that writing it all by hand.
However, while Threejs supports the glTF specification to a very high standard, and many 3D applications such as Blender, Maya, 3DS Max, etc., can also export the many features of glTF, there won't always be 100% compatibility between each implementation since each application is developed independently, uses different teams of people, and follows the priorities of different road maps and end use cases.
So, you will have to fill in the gaps regardless. Needless to say, glTF is the best format to use in almost all use-cases where you want to import a model into Three.js.
We will download some CC0 models, import them into Blender and export them as glTF suitable for our application.
We will load the models on demand as needed when the selection in the UI changes. They will then also be automatically cached in case they are selected in the UI again.
We will use the Drei HTML component to add annotations to our 3D models.
We will add placeholders, containing text, inside our models using Blender, and then read the userData while we load the model into the scene. For each userData.prop that we find, we will add a new HTML label in that position.
GLTFJSX is a command line tool that will read through a glTF model, and extract its components into a JSX equivalent.
When each of the components of the model are referenced using JSX it makes it easier to turn the different components on or off or add even more interaction to each.
GLTFJSX is beneficial if your model is quite large and contains many child-meshes, lights, materials, animations, etc., and you want to access those individual components within your code to add interactivity, or even only use parts of the original file.
GLTFJSX is not the only way to traverse a model and extract its components for individual use, but it does make it quick and easy to have the JSX automatically created for you.
Animating object transforms and material properties using interpolation (Lerp).
Lerping is a very minimal and simple technique used to quickly transition a property from one state to another.
In this lesson, I use the lerp technique to modify the cameras position. I also modify many objects positions, rotations and colours depending on whether that object was clicked, or the pointer is hovering over it.
I also quickly demonstrate the Drei Center helper, using Array.map to generate a series of objects in the JSX and introduce the React Three Fiber useThree hook.
In the first part of this lesson, we will use the key presses to move the box. The Box will move at 1 unit per second.
In the second part of this lesson, we add more boxes to the scene, and be able to move 1 or more boxes at the same time.
Ok, so at this point, we have covered the basics of many concepts which together should act as a good grounding for you to continue to build more complicated React Three Fiber applications.
This course won't cover every single object that you can find on the Threejs and React Three Fiber documentation. Both projects are enormous and cover many specialized disciplines. But you know now where to start when you have a new idea that you want to work on.
We have covered many subjects at a beginner level. From, creating a minimal starter template, understanding React fundamentals such as useRef, props, useState, useMemo, etc. We have looked at React Three Fiber useFrame and useLoader hooks, canvas and events. We have used several Drei components which are written specifically for React Three Fiber. Furthermore, we've implemented the Leva GUI in many ways. Moreover, we have looked at many of the smaller details of Three.js such as geometeries, materials, lights, shadows, loaders and some helpers.
If you get stuck when creating your React Three Fiber applications when asking questions, it is extremely helpful to provide a minimal example demonstrating your problem.
You can fork any of my CodeSandBox examples shown throughout this documentation, or even use any other examples that you've found written by other people.
Thanks for taking part in my course,
Sean Bradley
Updated code to React 19
Welcome to my course on React Three Fiber.
If you've ever tried to read the React Three Fiber documentation, you may have noticed the phrase,
"You need to be versed in both React and Threejs before rushing into this."
And this is the gap this course will help you fill.
We will look at the basics of using React Three Fiber with Threejs and introduce many of the great helpers that you also get when using the Drei library.
At the end, we would have covered many of the requirements to understand how to build your own React Three Fiber projects, and also understand the official examples better, so that you can confidently continue on your own to build much more complex applications in the future.
As we progress though the course, we will learn new concepts in each lesson, that will be in context from the previous lesson, so that you will understand better the problem that each new concept was designed to solve.
React Three Fiber is great for working with Threejs, and I am sure you will like it to. It's very clear, minimal, the code looks neat, and you will be able to create very robust applications in a very short amount of time.
All the code demonstrated is provided in the accompanying documentation that you also have access to for free, so that you will be able to easily copy/paste and participate alongside the videos.
So, there is much to learn, but in the end, you will have developed the techniques required to build your own Three.js projects declaratively, with re-usable self-contained components, that react to state and will be able to participate in the ever-expanding React ecosystem.
Thanks for taking part in my course, and I hope to see you there.
Sean Bradley