v10 deployment.Installation
pnpm add three @react-three/fiber@alphaTo try the v10 alpha:
pnpm add three@latest @react-three/fiber@alphaFiber is a React renderer, so it must pair with a major version of React, just like react-dom or react-native. It works with ReactDOM and React Native.
The v10 bounds are deliberate — they state the versions we have tested (React 19.0 through 19.3), and move when a newer one is verified. Installing v10 against three r184 will fail peer resolution.
Getting started with React Three Fiber is not nearly as hard as you might have thought, but various frameworks may require particular attention.
We've put together guides for getting started with each popular framework:
- Vite.js
- Next.js
- CDN w/o build tools
- React Native
If you just want to give it a try, fork this example on codesandbox!
Vite.js
vite will also work out of the box.
# Create app
npm create vite my-app
# Select react as framework
# Install dependencies
cd my-app
npm install three @react-three/fiber@alpha
# Start development server
npm run dev
Next.js
It should work out of the box but you will encounter untranspiled add-ons in the three.js ecosystem, in that case,
Next.js 13.1 or latest version
You need to add three to transpilePackages property in next.config.js:
transpilePackages: ['three'],
Next.js 13.0 or oldest version
You can install the next-transpile-modules module:
pnpm add next-transpile-modules --save-devthen, add this to your next.config.js
const withTM = require('next-transpile-modules')(['three'])
module.exports = withTM()
Make sure to check out our official next.js starter, too!
Without build tools
You can use React Three Fiber with browser-ready ES Modules from esm.sh and a JSX-like syntax powered by htm.
import ReactDOM from 'https://esm.sh/react-dom'
import React, { useRef, useState } from 'https://esm.sh/react'
import { Canvas, useFrame } from 'https://esm.sh/@react-three/fiber'
import htm from 'https://esm.sh/htm'
const html = htm.bind(React.createElement)
ReactDOM.render(html`<${Canvas}>...<//>`, document.getElementById('root'))
Full example
import ReactDOM from 'https://esm.sh/react-dom'
import React, { useRef, useState } from 'https://esm.sh/react'
import { Canvas, useFrame } from 'https://esm.sh/@react-three/fiber'
import htm from 'https://esm.sh/htm'
const html = htm.bind(React.createElement)
function Box(props) {
const meshRef = useRef()
const [hovered, setHover] = useState(false)
const [active, setActive] = useState(false)
useFrame(() => (meshRef.current.rotation.x = meshRef.current.rotation.y += 0.01))
return html` <mesh
...${props}
ref=${meshRef}
scale=${active ? 1.5 : 1}
onClick=${() => setActive(!active)}
onPointerOver=${() => setHover(true)}
onPointerOut=${() => setHover(false)}
>
<boxGeometry args=${[1, 1, 1]} />
<meshStandardMaterial color=${hovered ? 'hotpink' : 'orange'} />
</mesh>`
}
ReactDOM.render(
html` <${Canvas}>
<ambientLight />
<pointLight position=${[10, 10, 10]} />
<${Box} position=${[-1.2, 0, 0]} />
<${Box} position=${[1.2, 0, 0]} />
<//>`,
document.getElementById('root'),
)
React Native
React Native support lives in its own package, @react-three/native (in v9 and earlier this was the @react-three/fiber/native entry point). It uses expo-gl and expo-asset under the hood for WebGL2 bindings and ensuring interplay between Metro and three.js loaders.
@react-three/native is not on npm yet. Its source lives at pmndrs/native. Until it is published, React Native apps stay on v9 and import from @react-three/fiber/native.
To get started, create an app via expo or react-native:
# Create a managed/bare app
npx create-expo-app
cd my-app
# or
# Create and link bare app
npx react-native init my-app
npx install-expo-modules@latest
cd my-app
Then install dependencies (for manual installation or migration, see expo modules installation):
# Automatically install
expo install expo-gl
# Install NPM dependencies
npm install three @react-three/native
Some configuration may be required to tell the Metro bundler about your assets if you use useLoader or Drei abstractions like useGLTF and useTexture:
// metro.config.js
module.exports = {
resolver: {
sourceExts: ['js', 'jsx', 'json', 'ts', 'tsx', 'cjs', 'mjs'],
assetExts: ['glb', 'gltf', 'png', 'jpg'],
},
}
R3F's API is completely x-platform, so you can use events and hooks just as you would on the web.
Make sure to import from @react-three/native or @react-three/drei/native for correct IntelliSense and platform-specific abstractions.
iOS simulators often have incomplete or unreliable OpenGL ES support, which can cause EXC_BAD_ACCESS crashes when rendering 3D content. Always test on a physical iOS device (iPhone/iPad running iOS 16 or later) to ensure stable WebGL rendering.
import { Suspense } from 'react'
import { Canvas } from '@react-three/native'
import { useGLTF } from '@react-three/drei/native'
import modelPath from './path/to/model.glb'
function Model(props) {
const gltf = useGLTF(modelPath)
return <primitive {...props} object={gltf.scene} />
}
export default function App() {
return (
<Canvas>
<ambientLight />
<Suspense>
<Model />
</Suspense>
</Canvas>
)
}