React Three Fiber logo

React Three Fiber

A powerful React renderer for Three.js that allows you to build 3D scenes declaratively with re-usable components.

npm install react-three-fiber
29.8K39.5K/weekv6.0.132.75 KBMIT110 issues
Last updated: 2021-04-11
Star history chart for pmndrs/react-three-fiber

TL;DR

A React renderer for Three.js that lets you build 3D scenes using declarative components. It renders efficiently without overhead, treating Three.js objects as native React elements.

Ideal for developers wanting to bring React's state management, component lifecycle, and ecosystem into the 3D world. It is platform-agnostic and works wherever React does.

Why React Three Fiber?

React Three Fiber (R3F) isn't just a wrapper; it's a reconciler that drives Three.js. This means you get the full performance of Three.js combined with the sanity of React's component model. It solves the "spaghetti code" problem often found in imperative 3D programming by allowing you to compose complex scenes from reusable, self-contained components.

  • Declarative Scenegraph: Construct your 3D scene using JSX, making the hierarchy and structure immediately visible and understandable.
  • Component-Based: Encapsulate logic, styles, and assets into reusable components (e.g., <Player />, <Planet />) just like in standard web development.
  • Reactive Ecosystem: Seamlessly integrate with React state (Zustand, Redux) and hooks, making 3D objects react to data changes instantly.
  • Zero Overhead: R3F renders efficiently by managing instances and the render loop outside of React's overhead, matching plain Three.js performance.
  • Event System: Built-in raycasting handles pointer events (click, hover) on 3D objects as easily as DOM events (onClick, onPointerOver).

Code Snippet

This example demonstrates a self-contained, interactive 3D component. It handles its own animation loop and state changes, showcasing how cleanly logic couples with the view.

import { useRef, useState } from 'react'
import { Canvas, useFrame } from '@react-three/fiber'

function RotatingBox(props) {
  // This reference will give us direct access to the mesh
  const meshRef = useRef()
  
  // Set up state for the hovered and active state
  const [hovered, setHover] = useState(false)
  const [active, setActive] = useState(false)
  
  // Rotate mesh every frame, this is outside of React without overhead
  useFrame((state, delta) => (meshRef.current.rotation.x += delta))
  
  return (
    <mesh
      {...props}
      ref={meshRef}
      scale={active ? 1.5 : 1}
      onClick={() => setActive(!active)}
      onPointerOver={() => setHover(true)}
      onPointerOut={() => setHover(false)}>
      <boxGeometry args={[1, 1, 1]} />
      <meshStandardMaterial color={hovered ? 'hotpink' : 'orange'} />
    </mesh>
  )
}

export default function App() {
  return (
    <Canvas>
      <ambientLight intensity={Math.PI / 2} />
      <spotLight position={[10, 10, 10]} angle={0.15} penumbra={1} decay={0} intensity={Math.PI} />
      <pointLight position={[-10, -10, -10]} decay={0} intensity={Math.PI} />
      <RotatingBox position={[-1.2, 0, 0]} />
      <RotatingBox position={[1.2, 0, 0]} />
    </Canvas>
  )
}

The <Canvas> component acts as the entry point to the R3F scene, setting up the WebGL context. Inside, <RotatingBox> uses the useFrame hook to hook into the native render loop for smooth animations, bypassing React's render cycle for high-frequency updates.

Pros and Cons

No library is perfect; understanding the trade-offs is key to selecting the right tool.

Pros

  • Unmatched Ecosystem: Access to incredible helpers via @react-three/drei (cameras, controls, environments) and physics via @react-three/cannon.
  • Performance: Often outperforms manual Three.js code because it automatically handles optimization tasks like instance management and smart invalidation.
  • React Integration: You can use standard React hooks, Context, and libraries (like React Router or TanStack Query) directly within your 3D scene.

Cons

  • Requires Three.js Knowledge: It is not an abstraction over 3D concepts. You still need to understand meshes, materials, lights, and vectors to be effective.
  • Version Alignment: Keeping R3F, Three.js, and ecosystem libraries (Drei) in sync can sometimes lead to version conflict headaches.
  • Documentation Gap: While R3F docs are good, you often need to cross-reference Three.js documentation, translating imperative examples to declarative JSX mentally.

Comparison with Other 3D Solutions

The table below outlines the positioning differences between React Three Fiber and other approaches:

LibraryDesign PhilosophyBest ForPain Points
React Three FiberDeclarative Renderer
Bring React's component model to Three.js.
Interactive 3D Apps
Games, product configurators, and immersive web experiences.
Knowledge Barrier
Requires understanding both React patterns and 3D graphics concepts.
Spline (Runtime)Design-First
Export 3D scenes from a visual editor.
Design Portfolios
Simple interactions and beautiful, static visuals created by designers.
Limited Logic
Harder to implement complex game logic or deep integration with app state.
Babylon.jsEngine-First
A complete, opinionated 3D game engine for the web.
Full-Scale Games
Projects needing a robust, all-in-one game engine solution.
Imperative API
Integrating with React UI requires manual bridging and sync code.

Ecosystem & Extensions

React Three Fiber is the core of a massive ecosystem. These extensions are almost essential for serious development:

  • @react-three/drei: A growing collection of useful helpers, abstractions, and ready-made components (OrbitControls, Environment, Text, etc.).
  • @react-three/cannon: A physics hook library for R3F, making it easy to add gravity, collisions, and forces.
  • @react-three/postprocessing: A wrapper around postprocessing to easily add effects like Bloom, Depth of Field, and Glitch.
  • Leva: A GUI panel specifically designed for R3F to tweak variables in real-time.