react-three-fiber
39
总安装量
39
周安装量
#5301
全站排名
安装命令
npx skills add https://github.com/anthemflynn/ccmp --skill react-three-fiber
Agent 安装分布
opencode
23
claude-code
23
gemini-cli
22
codex
21
github-copilot
16
antigravity
15
Skill 文档
React Three Fiber
React Three Fiber (R3F) is a React renderer for Three.js. Write declarative, component-based 3D scenes using JSX.
Library Versions (2026)
- React Three Fiber: v9.5+
- @react-three/drei: v9.116+
- @react-three/rapier: v2+
- @react-three/postprocessing: v3+
- React: 19+ (concurrent features supported)
Decision Frameworks
When to Use R3F vs Vanilla Three.js
Is your app already React-based?
â Yes: Use R3F (natural integration)
â No: Consider vanilla Three.js
Do you need React state management?
â Yes: Use R3F (seamless state integration)
â No: Either works
Is the 3D scene the entire app?
â Yes: Either works (R3F has slight overhead)
â No, mixed with React UI: Use R3F
Performance-critical with millions of objects?
â Consider vanilla Three.js for maximum control
â R3F is fine for 99% of use cases
When to Use Which State Management
Local component state (single mesh color, hover)?
â useState / useRef
Shared between few components (selected object)?
â React Context or prop drilling
Global game/app state (score, inventory, settings)?
â Zustand (recommended for R3F)
Complex state with actions/reducers?
â Zustand with slices or Redux Toolkit
Need state persistence?
â Zustand with persist middleware
When to Use Which Drei Component
Need camera controls?
ââ Orbit around object â OrbitControls
ââ First-person â PointerLockControls
ââ Map/top-down â MapControls
ââ Smooth transitions â CameraControls
Need environment lighting?
ââ Quick preset â <Environment preset="sunset" />
ââ Custom HDR â <Environment files="/env.hdr" />
ââ Performance-sensitive â <Environment blur={0.5} />
Need text?
ââ 3D text in scene â <Text3D />
ââ 2D text billboards â <Text />
ââ HTML overlay â <Html />
Need loading?
ââ GLTF models â useGLTF
ââ Textures â useTexture
ââ Progress UI â useProgress
ââ Preloading â <Preload all />
Core Setup
import { Canvas } from '@react-three/fiber'
function App() {
return (
<Canvas
camera={{ position: [0, 0, 5], fov: 75 }}
gl={{ antialias: true }}
shadows
>
<ambientLight intensity={0.5} />
<directionalLight position={[10, 10, 5]} castShadow />
<mesh>
<boxGeometry args={[1, 1, 1]} />
<meshStandardMaterial color="orange" />
</mesh>
</Canvas>
)
}
Canvas Props
<Canvas
camera={{ position, fov, near, far }} // Camera config
gl={{ antialias, alpha, powerPreference }} // WebGL context
shadows // Enable shadow maps
dpr={[1, 2]} // Device pixel ratio range
frameloop="demand" // "always" | "demand" | "never"
style={{ width: '100%', height: '100vh' }}
onCreated={({ gl, scene, camera }) => {}} // Access internals
/>
Essential Hooks
useFrame – Animation Loop
import { useFrame } from '@react-three/fiber'
import { useRef } from 'react'
function SpinningBox() {
const meshRef = useRef()
useFrame((state, delta) => {
// state: { clock, camera, scene, gl, pointer, ... }
meshRef.current.rotation.y += delta
meshRef.current.position.y = Math.sin(state.clock.elapsedTime)
})
return (
<mesh ref={meshRef}>
<boxGeometry />
<meshStandardMaterial />
</mesh>
)
}
useThree – Access Internals
import { useThree } from '@react-three/fiber'
function CameraLogger() {
const { camera, gl, scene, size, viewport, pointer } = useThree()
// viewport: { width, height } in Three.js units
// size: { width, height } in pixels
// pointer: normalized mouse position (-1 to 1)
return null
}
useLoader – Asset Loading
import { useLoader } from '@react-three/fiber'
import { TextureLoader } from 'three'
import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader'
function Model() {
const gltf = useLoader(GLTFLoader, '/model.glb')
const texture = useLoader(TextureLoader, '/texture.jpg')
return <primitive object={gltf.scene} />
}
JSX to Three.js Mapping
// Three.js class â camelCase JSX element
// Constructor args â args prop (array)
// Properties â props
// THREE.Mesh
<mesh position={[0, 1, 0]} rotation={[0, Math.PI, 0]} scale={1.5}>
{/* THREE.BoxGeometry(1, 2, 1) */}
<boxGeometry args={[1, 2, 1]} />
{/* THREE.MeshStandardMaterial({ color: 'red' }) */}
<meshStandardMaterial color="red" roughness={0.5} />
</mesh>
// Nested properties use dash notation
<directionalLight
position={[5, 5, 5]}
castShadow
shadow-mapSize={[2048, 2048]}
shadow-camera-far={50}
/>
// Attach to parent properties
<mesh>
<boxGeometry />
<meshStandardMaterial>
<texture attach="map" image={img} />
</meshStandardMaterial>
</mesh>
Drei – Essential Helpers
Drei provides production-ready abstractions. Install: @react-three/drei
import {
OrbitControls,
PerspectiveCamera,
Environment,
useGLTF,
useTexture,
Text,
Html,
Float,
Stage,
ContactShadows,
Sky,
Stars,
} from '@react-three/drei'
Common Drei Components
// Camera controls
<OrbitControls enableDamping dampingFactor={0.05} />
// Environment lighting (HDR)
<Environment preset="sunset" background />
// Presets: apartment, city, dawn, forest, lobby, night, park, studio, sunset, warehouse
// Load GLTF with draco support
const { scene, nodes, materials } = useGLTF('/model.glb')
useGLTF.preload('/model.glb')
// Load textures
const [colorMap, normalMap] = useTexture(['/color.jpg', '/normal.jpg'])
// 3D Text
<Text fontSize={1} color="white" anchorX="center" anchorY="middle">
Hello World
</Text>
// HTML overlay in 3D space
<Html position={[0, 2, 0]} center transform occlude>
<div className="label">Click me</div>
</Html>
// Floating animation
<Float speed={2} rotationIntensity={0.5} floatIntensity={1}>
<mesh>...</mesh>
</Float>
// Quick studio lighting
<Stage environment="city" intensity={0.5}>
<Model />
</Stage>
// Soft shadows on ground
<ContactShadows position={[0, -0.5, 0]} opacity={0.5} blur={2} />
Event Handling
<mesh
onClick={(e) => {
e.stopPropagation()
console.log('clicked', e.point, e.face)
}}
onPointerOver={(e) => setHovered(true)}
onPointerOut={(e) => setHovered(false)}
onPointerMove={(e) => console.log(e.point)}
onPointerDown={(e) => {}}
onPointerUp={(e) => {}}
onDoubleClick={(e) => {}}
onContextMenu={(e) => {}}
>
Event object includes: point, face, faceIndex, distance, object, eventObject, camera, ray.
State Management
With Zustand (Recommended)
import { create } from 'zustand'
const useStore = create((set) => ({
score: 0,
gameState: 'idle',
addScore: (points) => set((state) => ({ score: state.score + points })),
startGame: () => set({ gameState: 'playing' }),
}))
function ScoreDisplay() {
const score = useStore((state) => state.score)
return <Text>{score}</Text>
}
function GameLogic() {
const addScore = useStore((state) => state.addScore)
useFrame(() => {
// Game logic that calls addScore
})
return null
}
With React Context
const GameContext = createContext()
function GameProvider({ children }) {
const [state, dispatch] = useReducer(reducer, initialState)
return (
<GameContext.Provider value={{ state, dispatch }}>
{children}
</GameContext.Provider>
)
}
// Wrap Canvas content
<Canvas>
<GameProvider>
<Scene />
</GameProvider>
</Canvas>
Performance Patterns
Instancing
import { Instances, Instance } from '@react-three/drei'
function Boxes({ count = 1000 }) {
return (
<Instances limit={count}>
<boxGeometry />
<meshStandardMaterial />
{Array.from({ length: count }, (_, i) => (
<Instance
key={i}
position={[Math.random() * 100, Math.random() * 100, Math.random() * 100]}
color={`hsl(${Math.random() * 360}, 50%, 50%)`}
/>
))}
</Instances>
)
}
Selective Rendering
// Only re-render when needed
<Canvas frameloop="demand">
{/* Call invalidate() to trigger render */}
</Canvas>
function Controls() {
const { invalidate } = useThree()
return <OrbitControls onChange={() => invalidate()} />
}
Memoization
// Memoize expensive components
const ExpensiveModel = memo(function ExpensiveModel({ url }) {
const gltf = useGLTF(url)
return <primitive object={gltf.scene.clone()} />
})
// Memoize materials/geometries outside components
const geometry = new THREE.BoxGeometry(1, 1, 1)
const material = new THREE.MeshStandardMaterial({ color: 'red' })
function Box() {
return (
<mesh geometry={geometry} material={material} />
)
}
Adaptive Performance
import { PerformanceMonitor, AdaptiveDpr, AdaptiveEvents } from '@react-three/drei'
<Canvas>
<PerformanceMonitor
onDecline={() => setQuality('low')}
onIncline={() => setQuality('high')}
>
<AdaptiveDpr pixelated />
<AdaptiveEvents />
<Scene quality={quality} />
</PerformanceMonitor>
</Canvas>
Related Skills
| When you need… | Use skill |
|---|---|
| Vanilla Three.js (no React) | â threejs |
| Optimize assets before loading | â asset-pipeline-3d |
| Debug visual/performance issues | â graphics-troubleshooting |
Reference Files
- references/drei.md – Complete Drei component reference
- references/physics.md – @react-three/rapier integration
- references/postprocessing.md – @react-three/postprocessing effects
- references/state.md – Zustand patterns for R3F