react-three-fiber
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.
```bash
npm install three @react-three/fiber
```
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:<mesh />
becomes new THREE.Mesh()
, and that happens dynamically. 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?
<mesh
{...props}
ref={ref}
scale={clicked ? 1.5 : 1}
onClick={(event) => click(!clicked)}
onPointerOver={(event) => hover(true)}
onPointerOut={(event) => hover(false)}>
<boxGeometry args={[1, 1, 1]} />
<meshStandardMaterial color={hovered ? 'hotpink' : 'orange'} />
</mesh>
)
}
createRoot(document.getElementById('root')).render(
<ambientLight />
<pointLight position={[10, 10, 10]} />
<Box position={[-1.2, 0, 0]} />
<Box position={[1.2, 0, 0]} />
,
)
```
Show TypeScript example
```bash
npm install @types/three
```
```tsx
import as THREE from 'three'
import { createRoot } from 'react-dom/client'
import React, { useRef, useState } from 'react'
import { Canvas, useFrame, ThreeElements } from '@react-three/fiber'
function Box(props: ThreeElements'mesh') {
const ref = useRef(null!)
const hovered, hover = useState(false)
const clicked, click = useState(false)
useFrame((state, delta) => (ref.current.rotation.x += delta))
return (
<mesh
{...props}
ref={ref}
scale={clicked ? 1.5 : 1}
onClick={(event) => click(!clicked)}
onPointerOver={(event) => hover(true)}
onPointerOut={(event) => hover(false)}>
<boxGeometry args={[1, 1, 1]} />
<meshStandardMaterial color={hovered ? 'hotpink' : 'orange'} />
</mesh>
)
}
createRoot(document.getElementById('root') as HTMLElement).render(
<ambientLight />
<pointLight position={[10, 10, 10]} />
<Box position={[-1.2, 0, 0]} />
<Box position={[1.2, 0, 0]} />
,
)
```
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.
```bash
Install expo-cli, this will create our app
npm install expo-cli -g
Create app and cd into it
expo init my-app
cd my-app
Install dependencies
npm install three @react-three/fiber@beta react@rc
Start
expo start
```
Some configuration may be required to tell the Metro bundler about your assets if you use useLoader
or Drei abstractions like useGLTF
and useTexture
:
```js
// metro.config.js
module.exports = {
resolver: {
sourceExts: ['js', 'jsx', 'json', 'ts', 'tsx', 'cjs'],
assetExts: ['glb', 'png', 'jpg'],
},
}
```
```tsx
import React, { useRef, useState } from 'react'
import { Canvas, useFrame } from '@react-three/fiber/native'
function Box(props) {
const mesh = useRef(null)
const hovered, setHover = useState(false)
const active, setActive = useState(false)
useFrame((state, delta) => (mesh.current.rotation.x += delta))
return (
<mesh
{...props}
ref={mesh}
scale={active ? 1.5 : 1}
onClick={(event) => setActive(!active)}
onPointerOver={(event) => setHover(true)}
onPointerOut={(event) => setHover(false)}>
<boxGeometry args={[1, 1, 1]} />
<meshStandardMaterial color={hovered ? 'hotpink' : 'orange'} />
</mesh>
)
}
export default function App() {
return (
<Canvas>
<ambientLight />
<pointLight position={[10, 10, 10]} />
<Box position={[-1.2, 0, 0]} />
<Box position={[1.2, 0, 0]} />
</Canvas>
)
}
```
---
Documentation, tutorials, examples
Visit docs.pmnd.rs
Fundamentals
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:
- Make sure you have a basic grasp of Threejs. Keep that site open.
- When you know what a scene is, a camera, mesh, geometry, material, fork the demo above.
- Look up the JSX elements that you see (mesh, ambientLight, etc), all threejs exports are native to three-fiber.
- Try changing some values, scroll through our API to see what the various settings and hooks do.
- Do's and don'ts for performance and best practices
Ecosystem
@react-three/gltfjsx
– turns GLTFs into JSX components
@react-three/drei
– useful helpers for react-three-fiber
@react-three/postprocessing
– post-processing effects
@react-three/flex
– flexbox for react-three-fiber
@react-three/xr
– VR/AR controllers and events
@react-three/cannon
– physics based hooks
@react-three/a11y
– real a11y for your scene
zustand
– state management
react-spring
– a spring-physics-based animation library
react-use-gesture
– mouse/touch gestures
leva
– create GUI controls in seconds
How to contribute
If you like this project, please consider helping out. All contributions are welcome as well as donations to Opencollective, or in crypto BTC: 36fuguTPxGCNnYZSRdgdh6Ea94brCAjMbH
, ETH: 0x6E3f79Ea1d0dcedeb33D3fC6c34d2B1f156F2682
.