| <h1>react-three-fiber</h1> | |
| [](https://npmjs.com/package/@react-three/fiber) | |
| [](https://npmjs.com/package/@react-three/fiber) | |
| [](https://twitter.com/pmndrs) | |
| [](https://discord.gg/ZZjjNvJ) | |
| [](https://opencollective.com/react-three-fiber) | |
| [](https://blockchain.com/eth/address/0x6E3f79Ea1d0dcedeb33D3fC6c34d2B1f156F2682) | |
| [](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) – turns GLTFs into JSX components | |
| - [`@react-three/drei`](https://github.com/pmndrs/drei) – useful helpers for react-three-fiber | |
| - [`@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/cannon`](https://github.com/pmndrs/use-cannon) – physics based hooks | |
| - [`@react-three/a11y`](https://github.com/pmndrs/react-three-a11y) – real a11y for your scene | |
| - [`zustand`](https://github.com/pmndrs/zustand) – state management | |
| - [`react-spring`](https://github.com/pmndrs/react-spring) – a spring-physics-based animation library | |
| - [`react-use-gesture`](https://github.com/pmndrs/react-use-gesture) – mouse/touch gestures | |
| - [`leva`](https://github.com/pmndrs/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](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> | |