react-three-fiber

A React renderer for Three.js

README

@react-three/fiber

Version Downloads Twitter Discord Open Collective ETH BTC


react-three-fiber is a React renderer for threejs.

Build your scene declaratively with re-usable, self-contained components that react to state, are readily interactive and can participate in React's ecosystem.

  1. ```bash
  2. npm install three @types/three @react-three/fiber
  3. ```

Does it have limitations?


None. Everything that works in Threejs will work here without exception.

Is it slower than plain Threejs?


No. There is no overhead. Components render outside of React. It outperforms Threejs in scale due to Reacts scheduling abilities.

Can it keep up with frequent feature updates to Threejs?


Yes. It merely expresses Threejs in JSX, `` dynamically turns into `new THREE.Mesh()`. If a new Threejs version adds, removes or changes features, it will be available to you instantly without depending on updates to this library.

What does it look like?


Let's make a re-usable component that has its own state, reacts to user-input and participates in the render-loop. (live demo).

  1. ```jsx
  2. import { createRoot } from 'react-dom/client'
  3. import React, { useRef, useState } from 'react'
  4. import { Canvas, useFrame } from '@react-three/fiber'

  5. function Box(props) {
  6.   // This reference gives us direct access to the THREE.Mesh object
  7.   const ref = useRef()
  8.   // Hold state for hovered and clicked events
  9.   const [hovered, hover] = useState(false)
  10.   const [clicked, click] = useState(false)
  11.   // Subscribe this component to the render-loop, rotate the mesh every frame
  12.   useFrame((state, delta) => (ref.current.rotation.x += 0.01))
  13.   // Return the view, these are regular Threejs elements expressed in JSX
  14.   return (
  15.     <mesh
  16.       {...props}
  17.       ref={ref}
  18.       scale={clicked ? 1.5 : 1}
  19.       onClick={(event) => click(!clicked)}
  20.       onPointerOver={(event) => hover(true)}
  21.       onPointerOut={(event) => hover(false)}>
  22.       <boxGeometry args={[1, 1, 1]} />
  23.       <meshStandardMaterial color={hovered ? 'hotpink' : 'orange'} />
  24.     </mesh>
  25.   )
  26. }

  27. createRoot(document.getElementById('root')).render(
  28.   <Canvas>
  29.     <ambientLight />
  30.     <pointLight position={[10, 10, 10]} />
  31.     <Box position={[-1.2, 0, 0]} />
  32.     <Box position={[1.2, 0, 0]} />
  33.   </Canvas>,
  34. )
  35. ```

Show TypeScript example
  
  1. ```bash
  2. npm install @types/three
  3. ```

  1. ```tsx
  2. import * as THREE from 'three'
  3. import { createRoot } from 'react-dom/client'
  4. import React, { useRef, useState } from 'react'
  5. import { Canvas, useFrame, ThreeElements } from '@react-three/fiber'

  6. function Box(props: ThreeElements['mesh']) {
  7.   const ref = useRef<THREE.Mesh>(null!)
  8.   const [hovered, hover] = useState(false)
  9.   const [clicked, click] = useState(false)
  10.   useFrame((state, delta) => (ref.current.rotation.x += 0.01))
  11.   return (
  12.     <mesh
  13.       {...props}
  14.       ref={ref}
  15.       scale={clicked ? 1.5 : 1}
  16.       onClick={(event) => click(!clicked)}
  17.       onPointerOver={(event) => hover(true)}
  18.       onPointerOut={(event) => hover(false)}>
  19.       <boxGeometry args={[1, 1, 1]} />
  20.       <meshStandardMaterial color={hovered ? 'hotpink' : 'orange'} />
  21.     </mesh>
  22.   )
  23. }

  24. createRoot(document.getElementById('root') as HTMLElement).render(
  25.   <Canvas>
  26.     <ambientLight />
  27.     <pointLight position={[10, 10, 10]} />
  28.     <Box position={[-1.2, 0, 0]} />
  29.     <Box position={[1.2, 0, 0]} />
  30.   </Canvas>,
  31. )
  32. ```

Live demo: https://codesandbox.io/s/icy-tree-brnsm?file=/src/App.tsx

Show React Native example

This example relies on react 18 and uses expo-cli, but you can create a bare project with their template or with the react-native CLI.

  1. ```bash
  2. # Install expo-cli, this will create our app
  3. npm install expo-cli -g
  4. # Create app and cd into it
  5. expo init my-app
  6. cd my-app
  7. # Install dependencies
  8. npm install three @react-three/fiber@beta react@rc
  9. # Start
  10. expo start
  11. ```

Some configuration may be required to tell the Metro bundler about your assets if you use useLoader or Drei abstractions like useGLTF and useTexture:

  1. ```js
  2. // metro.config.js
  3. module.exports = {
  4.   resolver: {
  5.     sourceExts: ['js', 'jsx', 'json', 'ts', 'tsx', 'cjs'],
  6.     assetExts: ['glb', 'png', 'jpg'],
  7.   },
  8. }
  9. ```

  1. ```tsx
  2. import React, { useRef, useState } from 'react'
  3. import { Canvas, useFrame } from '@react-three/fiber/native'
  4. function Box(props) {
  5.   const mesh = useRef(null)
  6.   const [hovered, setHover] = useState(false)
  7.   const [active, setActive] = useState(false)
  8.   useFrame((state, delta) => (mesh.current.rotation.x += 0.01))
  9.   return (
  10.     <mesh
  11.       {...props}
  12.       ref={mesh}
  13.       scale={active ? 1.5 : 1}
  14.       onClick={(event) => setActive(!active)}
  15.       onPointerOver={(event) => setHover(true)}
  16.       onPointerOut={(event) => setHover(false)}>
  17.       <boxGeometry args={[1, 1, 1]} />
  18.       <meshStandardMaterial color={hovered ? 'hotpink' : 'orange'} />
  19.     </mesh>
  20.   )
  21. }
  22. export default function App() {
  23.   return (
  24.     <Canvas>
  25.       <ambientLight />
  26.       <pointLight position={[10, 10, 10]} />
  27.       <Box position={[-1.2, 0, 0]} />
  28.       <Box position={[1.2, 0, 0]} />
  29.     </Canvas>
  30.   )
  31. }
  32. ```



Documentation, tutorials, examples



First steps


You need to be versed in both React and Threejs before rushing into this. If you are unsure about React consult the official React docs, especially the section about hooks. As for Threejs, make sure you at least glance over the following links:

1. Make sure you have a basic grasp of Threejs. Keep that site open.
2. When you know what a scene is, a camera, mesh, geometry, material, fork the demo above.
3. Look up the JSX elements that you see (mesh, ambientLight, etc), _all_ threejs exports are native to three-fiber.
4. Try changing some values, scroll through our API to see what the various settings and hooks do.

Some helpful material:

- Discover Threejs, especially the Tips and Tricks chapter for best practices
- Bruno Simons Threejs Jouney, arguably the best learning resource, now includes a full R3F chapter


Ecosystem


There is a vibrant and extensive eco system around three-fiber, full of libraries, helpers and abstractions.

- [@react-three/drei](https://github.com/pmndrs/drei) – useful helpers, this is an eco system in itself
- [@react-three/gltfjsx](https://github.com/pmndrs/gltfjsx) – turns GLTFs into JSX components
- [@react-three/postprocessing](https://github.com/pmndrs/react-postprocessing) – post-processing effects
- [@react-three/flex](https://github.com/pmndrs/react-three-flex) – flexbox for react-three-fiber
- [@react-three/xr](https://github.com/pmndrs/react-xr) – VR/AR controllers and events
- [@react-three/csg](https://github.com/pmndrs/react-three-csg) – constructive solid geometry
- [@react-three/rapier](https://github.com/pmndrs/react-three-rapier) – 3D physics using Rapier
- [@react-three/cannon](https://github.com/pmndrs/use-cannon) – 3D physics using Cannon
- [@react-three/p2](https://github.com/pmndrs/use-p2) – 2D physics using P2
- [@react-three/a11y](https://github.com/pmndrs/react-three-a11y) – real a11y for your scene
- [@react-three/gpu-pathtracer](https://github.com/pmndrs/react-three-gpu-pathtracer) – realistic path tracing
- [create-r3f-app next](https://github.com/pmndrs/react-three-next) – nextjs starter
- [lamina](https://github.com/pmndrs/lamina) – layer based shader materials
- [zustand](https://github.com/pmndrs/zustand) – flux based state management
- [jotai](https://github.com/pmndrs/jotai) – atoms based state management
- [valtio](https://github.com/pmndrs/valtio) – proxy based state management
- [react-spring](https://github.com/pmndrs/react-spring) – a spring-physics-based animation library
- [framer-motion-3d](https://www.framer.com/docs/three-introduction/) – framer motion, a popular animation library
- [use-gesture](https://github.com/pmndrs/react-use-gesture) – mouse/touch gestures
- [leva](https://github.com/pmndrs/leva) – create GUI controls in seconds
- [maath](https://github.com/pmndrs/maath) – a kitchen sink for math helpers
- [miniplex](https://github.com/hmans/miniplex) – ECS (entity management system)
- [composer-suite](https://github.com/hmans/composer-suite) – composing shaders, particles, effects and game mechanics

How to contribute


If you like this project, please consider helping out. All contributions are welcome as well as donations to Opencollective, or in cryptoBTC: 36fuguTPxGCNnYZSRdgdh6Ea94brCAjMbH, ETH: 0x6E3f79Ea1d0dcedeb33D3fC6c34d2B1f156F2682.

Backers


Thank you to all our backers! 🙏


Contributors


This project exists thanks to all the people who contribute.