React Three Fiber

How to Create React 3D Animation with three.js and react-three-fiber Library

August 13, 2022
Uncle Big Bay
React.js

The Fastest Way to Build React UI

Convert Figma designs to production-ready React.js code. Build stunning apps and landing pages faster than your peers and competitors.

3D animation is one of many ways that frontend development has evolved over time. They boost user interaction with your website and make it appear as if you’re engaging with real-world objects. This article will go through how to utilize three.js and the react-three-fiber library to implement 3D animation in your React application.

What is three.js?

Three.js is a cross-browser Javascript library that allows you to create and manipulate interactive 2D and 3D graphics animation in your browser using the HTML5 canvas API and WebGL API.

3D graphics animation

Canvas API is an HTML5 standard that allows the creation of 2D graphics, animation, data visualization, photo manipulation, and real-time video processing using the <canvas> HTML tag.

Because the Canvas API is mainly focused on 2D rendering, we have WebGL for 3D.

WebGL API stands for Web Graphics Library. It makes it possible to create high-performance interactive 2D and 3D graphics for the web.

What can you do with three.js?

Aside from animation, three.js may be used to create game graphics, as well as high-quality 3D react rendering and post-processing effects.

3D rendering

You can check out more three.js project examples here.

What is react-three-fiber?

react-three-fiber is an open-source react-renderer for three.js. It makes it easier to use three.js in React by exposing reusable and self-contained components from three.js.

React three fiber

Using react-three-fiber three.js renderer is one of the best practices for using three.js with React, as you can see the reusable and self-contained components.

Setting up our react-three-fiber project

Now that we know what three.js and react-three-fiber are. In this section, we’ll explore how to set up the fiber library in React and create a basic 3D component that participates in the render loop.

Step 1 – Creating a new react project

To demonstrate how 3D with react-three-fiber works in React, we’ll create a new react app named my-3d-react-app ****to experiment. This tutorial makes use of CRA (Create React App).

Create a new React my-3d-react-app application with the command below:

npx create-react-app my-3d-react-app

Navigate into the newly created my-3d-react-app ****directory:

cd my-3d-react-app

Next, start the React app server:

npm run start

Your React app will open a new tab on your browser and should look something like this:

React three fiber project

Step 2 – Installing react-three-fiber

Run the command below to install react-three-fiber in your React application.

npm install three @react-three/fiber

Step 3 – Creating a 3D Cylinder with Mesh Geometry Component

To render objects to the scene, we’ll make a re-usable 3D component with mesh which is used to hold the geometry and the material needed to represent a shape in 3D space.

We’ll make a new mesh with a cylinderGeometry and a meshStandardMaterial that will attach to their parent automatically. You can learn how react-three-fiber attach objects to their parent here.

In your src folder:

  • Create a new component folder
  • Next, create a new Cylinder3d.jsx file inside the component folder
  • Copy and paste the following code inside the Cylinder3d.jsx file:
import React, { useRef, useState } from "react";
import { useFrame } from "@react-three/fiber";

function Cylinder3d(props) {
  // This reference gives us direct access to the THREE.Mesh object
  const ref = useRef();
  // Hold state for hovered and clicked events
  const [hovered, hover] = useState(false);
  const [clicked, click] = useState(false);
  // Subscribe this component to the render-loop, rotate the mesh every frame
  useFrame((state, delta) => (ref.current.rotation.x += 0.01));
  // Return the view, these are regular Threejs elements expressed in JSX
  return (
    <mesh
      {...props}
      ref={ref}
      scale={clicked ? 1.5 : 1}
      onClick={(event) => click(!clicked)}
      onPointerOver={(event) => hover(true)}
      onPointerOut={(event) => hover(false)}
    >
      <cylinderGeometry args={[1, 1, 1]} />
      <meshStandardMaterial
        wireframe={props.wireframe}
        color={hovered ? "hotpink" : "orange"}
      />
    </mesh>
  );
}

export default Cylinder3d;

From the Cylinder3d component above:

  • We import the useFrame hook from react fiber. This hook will allow us to create effects and control such as rotation.
  • We also want to keep track of the hover state of the Cylinder3d component; we want the color to change from orange to hotpink on mouse hover.
  • The mesh state reacts to user input and participates in events through the onClick, onPointerOver, and onPointerOut props.
  • We also set the wireframe prop which expects either a true or false value.

Step 4 – Rendering the 3D Cylinder Component

Replace your App.js file with the code below:

import "./App.css";
import { Canvas } from "@react-three/fiber";
import Cylinder3d from "./component/Cylinder3d";

function App() {
  return (
    <>
      <section className='App-header'>
        <Canvas>
          {/* <pointLight position={[10, 10, 10]} /> */}
          {/* <ambientLight /> */}
          <Cylinder3d position={[-1.2, 0, 0]} />
          <Cylinder3d position={[1.2, 0, 0]} />
        </Canvas>
      </section>
    </>
  );
}

export default App;

Our 3D Cylinder should look something like this:

React three fiber project

Step 5 – Adding Lights to Scene

In this section, we’re going to add and see the effect of the pointLight and the ambientLight lights on the scene.

  • Adding <pointLight/> to the scene

PointLight is a light that gets emitted from a single point in all directions.

Uncomment the following line within that <Canvas /> component in the App.js file:

<pointLight position={[10, 10, 10]} />

We use the position prop to define the direction of the light on the 3D cylinder.

This will add light to our 3D cylinder as shown below:

React three fiber project
  • Adding <ambientLight/> to the scene

This light globally illuminates all objects in the scene equally and it does not have a direction.

Uncomment the <ambientLight /> within the <Canvas /> component in the App.js file:

<ambientLight />

The combination of the <pointLight/> and the <ambientLight/> will produce the following result:

React three fiber project

The hover and click state will look something like this:

3D hover and click

Step 5 – Final Output

For the final demonstration, we’re going to render multiple versions of the 3D cylinder with different positions and props.

Update your App.js file with the code below:

import "./App.css";
import { Canvas } from "@react-three/fiber";
import Cylinder3d from "./component/Cylinder3d";

function App() {
  return (
    <>
      <section className='App-header'>
        {/* Canvas 1 */}
        <Canvas>
          <pointLight position={[10, 10, 10]} />
          <ambientLight />
          <Cylinder3d position={[-1.2, 0, 0]} />
          <Cylinder3d position={[1.2, 0, 0]} />
        </Canvas>

        {/* Canvas 2 */}
        <Canvas>
          <pointLight position={[10, 10, 10]} />
          <ambientLight intensity={0.5} />
          <Cylinder3d position={[-1.2, 0, 0]} wireframe={true} />
          <Cylinder3d position={[1.2, 0, 0]} wireframe={true} />
        </Canvas>

        {/* Canvas 3 */}
        <Canvas>
          <pointLight position={[10, 10, 10]} />
          <ambientLight color={"red"} />
          <Cylinder3d position={[-1.2, 0, 0]} />
          <Cylinder3d position={[1.2, 0, 0]} />
        </Canvas>
      </section>
    </>
  );
}

export default App;

From the above component:

In canvas 2

  • We set an intensity prop of the ambientLight to 0.5.
  • We set the wireframe prop to true which gives the cylinder an outline look.

In canvas 3

  • We set the ambientLight color to red.

Our 3D cylinder final output should look something like this:

3D cylinder

The hover and click state will look something like this:

3D cylinder

react-three-fiber APIs, Hooks, and Events

The react fiber library has several APIs, Hooks, and Events that are not covered in this tutorial, you can check out the complete fiber documentation here.

Alternatives to three.js

If you want to explore more on 3D rendering, below are useful tools and alternatives to the three.js library:

Frequently asked questions

Does React three fiber work with react native?

Ans: Fiber is compatible with React v18. 0.0+ and works with ReactDOM and React Native. You can check the React Native installation guide here.

How does react-three-fiber work?

Ans: react-three-fiber is a three.js renderer, it enables you to use three.js declaratively with re-usable react 3D components. If you’re interested in learning the inner work of this library, check this guide.

Does three.js work with React?

Ans: Yes it does, but for best practice, you have to make use of react-three-fiber.

Wrapping Up

In this tutorial, we learned about three.js, and how to render it in React using the react-three-fiber library, an open source react renderer for three.js.

You can find the complete source code of this tutorial in this repository.

Where do you go next?

You can learn more about building projects with three.js and react-three-fiber from the videos below:

  • three.js and react three fiber playlist tutorial:
  • Learn how react-3-fiber works under the hood

If you’re looking out for cool React tools that’ll help you to write component code faster and be production ready faster than all the people in your competition, don’t forget to check out the CopyCat plugin for React!

Happy Coding!

Interesting Reads From Our Blogs

Related Articles

Convert Figma To React

Convert Figma designs to production-ready React.js code. Build stunning apps and landing pages faster than your peers and competitors.

Convert Design to Code