react-three-fiber is a React renderer for threejs.
npm install three @react-three/fiber
Build your scene declaratively with re-usable, self-contained components that react to state, are readily interactive and can tap into React's ecosystem.
None. Everything that works in Threejs will work here without exception.
Yes. There is no hard dependency on a particular Threejs version, it does not wrap or duplicate a single Threejs class. It merely expresses Threejs in JSX: <mesh />
becomes new THREE.Mesh()
, and that happens dynamically.
No. There is no additional overhead. Components participate in a unified renderloop outside of React. It outperforms Threejs in scale due to Reacts scheduling abilities.
Let's make a re-usable component that has its own state, reacts to user-input and participates in the render-loop. (live demo). |
import ReactDOM from 'react-dom'
import React, { useRef, useState } from 'react'
import { Canvas, useFrame } from '@react-three/fiber'
function Box(props) {
// This reference will give us direct access to the THREE.Mesh object
const ref = useRef()
// Set up state for the hovered and active state
const [hovered, setHover] = useState(false)
const [active, setActive] = 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={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>
)
}
ReactDOM.render(
<Canvas>
<ambientLight />
<pointLight position={[10, 10, 10]} />
<Box position={[-1.2, 0, 0]} />
<Box position={[1.2, 0, 0]} />
</Canvas>,
document.getElementById('root'),
)
Show TypeScript example
npm install @types/three
import * as THREE from 'three'
import ReactDOM from 'react-dom'
import React, { useRef, useState } from 'react'
import { Canvas, useFrame } from '@react-three/fiber'
function Box(props: JSX.IntrinsicElements['mesh']) {
const ref = useRef<THREE.Mesh>(null!)
const [hovered, setHover] = useState(false)
const [active, setActive] = useState(false)
useFrame((state, delta) => (ref.current.rotation.x += 0.01))
return (
<mesh
{...props}
ref={ref}
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>
)
}
ReactDOM.render(
<Canvas>
<ambientLight />
<pointLight position={[10, 10, 10]} />
<Box position={[-1.2, 0, 0]} />
<Box position={[1.2, 0, 0]} />
</Canvas>,
document.getElementById('root'),
)
Live demo: https://codesandbox.io/s/icy-tree-brnsm?file=/src/App.tsx
Visit docs.pmnd.rs
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.
Some reading material:
- Threejs-docs
- Threejs-examples
- Threejs-fundamentals
- Discover Threejs
- Do's and don'ts for performance and best practices
- react-three-fiber alligator.io tutorial by @dghez_
@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 hookszustand
β state managementreact-spring
β a spring-physics-based animation libraryreact-use-gesture
β mouse/touch gesturesleva
β create GUI controls in seconds
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
.
Thank you to all our backers! π
This project exists thanks to all the people who contribute.