File size: 10,361 Bytes
bf237c2
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
<h1>react-three-fiber</h1>

[![Version](https://img.shields.io/npm/v/@react-three/fiber?style=flat&colorA=000000&colorB=000000)](https://npmjs.com/package/@react-three/fiber)
[![Downloads](https://img.shields.io/npm/dt/react-three-fiber.svg?style=flat&colorA=000000&colorB=000000)](https://npmjs.com/package/@react-three/fiber)
[![Twitter](https://img.shields.io/twitter/follow/pmndrs?label=%40pmndrs&style=flat&colorA=000000&colorB=000000&logo=twitter&logoColor=000000)](https://twitter.com/pmndrs)
[![Discord](https://img.shields.io/discord/740090768164651008?style=flat&colorA=000000&colorB=000000&label=discord&logo=discord&logoColor=000000)](https://discord.gg/ZZjjNvJ)
[![Open Collective](https://img.shields.io/opencollective/all/react-three-fiber?style=flat&colorA=000000&colorB=000000)](https://opencollective.com/react-three-fiber)
[![ETH](https://img.shields.io/badge/ETH-f5f5f5?style=flat&colorA=000000&colorB=000000)](https://blockchain.com/eth/address/0x6E3f79Ea1d0dcedeb33D3fC6c34d2B1f156F2682)
[![BTC](https://img.shields.io/badge/BTC-f5f5f5?style=flat&colorA=000000&colorB=000000)](https://blockchain.com/btc/address/36fuguTPxGCNnYZSRdgdh6Ea94brCAjMbH)

react-three-fiber is a <a href="https://reactjs.org/docs/codebase-overview.html#renderers">React renderer</a> 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 React's 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?

<table>
  <tbody>
    <tr>

      <td>Let's make a re-usable component that has its own state, reacts to user-input and participates in the render-loop. (<a href="https://codesandbox.io/s/rrppl0y8l4?file=/src/App.js">live demo</a>).</td>

      <td>

        <a href="https://codesandbox.io/s/rrppl0y8l4">

          <img src="https://i.imgur.com/sS4ArrZ.gif" />

        </a>

      </td>

    </tr>

  </tbody>

</table>


```jsx

import { createRoot } from 'react-dom/client'

import React, { useRef, useState } from 'react'

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



function Box(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 += delta))

  // 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)}>

      <boxGeometry args={[1, 1, 1]} />

      <meshStandardMaterial color={hovered ? 'hotpink' : 'orange'} />

    </mesh>

  )

}



createRoot(document.getElementById('root')).render(

  <Canvas>

    <ambientLight />

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

    <Box position={[-1.2, 0, 0]} />

    <Box position={[1.2, 0, 0]} />

  </Canvas>,

)

```

<details>
  <summary>Show TypeScript example</summary>
  
```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<THREE.Mesh>(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(

  <Canvas>

    <ambientLight />

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

    <Box position={[-1.2, 0, 0]} />

    <Box position={[1.2, 0, 0]} />

  </Canvas>,

)

```

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

</details>

<details>
  <summary>Show React Native example</summary>

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 react

# 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>

  )

}

```

</details>

---

# Documentation, tutorials, examples

Visit [docs.pmnd.rs](https://docs.pmnd.rs/react-three-fiber)

<a href="https://docs.pmnd.rs/react-three-fiber"><img src="/docs/preview.jpg"></a>

# 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](https://react.dev/learn), especially [the section about hooks](https://react.dev/reference/react). As for Threejs, make sure you at least glance over the following links:

1. Make sure you have a [basic grasp of Threejs](https://threejs.org/docs/index.html#manual/en/introduction/Creating-a-scene). Keep that site open.
2. When you know what a scene is, a camera, mesh, geometry, material, fork the [demo above](https://github.com/pmndrs/react-three-fiber#what-does-it-look-like).
3. [Look up](https://threejs.org/docs/index.html#api/en/objects/Mesh) 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](https://docs.pmnd.rs/react-three-fiber/API) to see what the various settings and hooks do.

Some reading material:

- [Threejs-docs](https://threejs.org/docs)
- [Threejs-examples](https://threejs.org/examples)
- [Threejs-fundamentals](https://threejs.org/manual/#en/fundamentals)
- [three.js-journey](https://threejs-journey.com)
- [Discover Threejs](https://discoverthreejs.com)
- [Do's and don'ts](https://discoverthreejs.com/tips-and-tricks) for performance and best practices
- [react-three-fiber alligator.io tutorial](https://alligator.io/react/react-with-threejs) by [@dghez\_](https://twitter.com/dghez_)

# Ecosystem

- [`@react-three/gltfjsx`](https://github.com/pmndrs/gltfjsx) &ndash; turns GLTFs into JSX components
- [`@react-three/drei`](https://github.com/pmndrs/drei) &ndash; useful helpers for react-three-fiber
- [`@react-three/postprocessing`](https://github.com/pmndrs/react-postprocessing) &ndash; post-processing effects
- [`@react-three/flex`](https://github.com/pmndrs/react-three-flex) &ndash; flexbox for react-three-fiber
- [`@react-three/xr`](https://github.com/pmndrs/react-xr) &ndash; VR/AR controllers and events
- [`@react-three/cannon`](https://github.com/pmndrs/use-cannon) &ndash; physics based hooks
- [`@react-three/a11y`](https://github.com/pmndrs/react-three-a11y) &ndash; real a11y for your scene
- [`zustand`](https://github.com/pmndrs/zustand) &ndash; state management
- [`react-spring`](https://github.com/pmndrs/react-spring) &ndash; a spring-physics-based animation library
- [`react-use-gesture`](https://github.com/pmndrs/react-use-gesture) &ndash; mouse/touch gestures
- [`leva`](https://github.com/pmndrs/leva) &ndash; 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](https://opencollective.com/react-three-fiber), or in crypto `BTC: 36fuguTPxGCNnYZSRdgdh6Ea94brCAjMbH`, `ETH: 0x6E3f79Ea1d0dcedeb33D3fC6c34d2B1f156F2682`.

#### Backers

Thank you to all our backers! 🙏

<a href="https://opencollective.com/react-three-fiber#backers" target="_blank">
  <img src="https://opencollective.com/react-three-fiber/backers.svg?width=890"/>
</a>

#### Contributors

This project exists thanks to all the people who contribute.

<a href="https://github.com/pmndrs/react-three-fiber/graphs/contributors">
  <img src="https://opencollective.com/react-three-fiber/contributors.svg?width=890" />
</a>