0
# Hooks
1
2
React hooks for animations, state management, and Three.js integration. These hooks provide seamless integration between React patterns and Three.js functionality, enabling declarative 3D programming.
3
4
## Capabilities
5
6
### useAnimations
7
8
Animation control hook for managing GLTF animations with play, pause, and crossfading capabilities.
9
10
```typescript { .api }
11
/**
12
* Animation control hook for GLTF animations
13
* @param clips - Animation clips from GLTF loader
14
* @param root - Target object for animations
15
* @returns Animation API with controls and state
16
*/
17
function useAnimations<T extends AnimationClip>(
18
clips: T[],
19
root?: React.RefObject<Object3D>
20
): Api<T>;
21
22
interface Api<T extends AnimationClip> {
23
/** Reference to the animated object */
24
ref: React.RefObject<Object3D | undefined | null>;
25
/** Animation clips array */
26
clips: AnimationClip[];
27
/** Three.js animation mixer */
28
mixer: AnimationMixer;
29
/** Animation clip names */
30
names: T['name'][];
31
/** Animation actions mapped by name */
32
actions: { [key in T['name']]: AnimationAction | null };
33
}
34
```
35
36
**Usage Examples:**
37
38
```typescript
39
import { useAnimations, useGLTF } from '@react-three/drei';
40
41
function AnimatedModel() {
42
const group = useRef();
43
const { nodes, materials, animations } = useGLTF('/model.glb');
44
const { actions, names } = useAnimations(animations, group);
45
46
// Play animation on mount
47
useEffect(() => {
48
actions['Walk']?.play();
49
}, [actions]);
50
51
// Control animations
52
const switchAnimation = (name) => {
53
// Crossfade between animations
54
actions[name]?.reset().fadeIn(0.5).play();
55
Object.keys(actions).forEach((key) => {
56
if (key !== name) {
57
actions[key]?.fadeOut(0.5);
58
}
59
});
60
};
61
62
return (
63
<group ref={group}>
64
<primitive object={nodes.Scene} />
65
{/* Animation controls */}
66
<Html>
67
{names.map((name) => (
68
<button key={name} onClick={() => switchAnimation(name)}>
69
{name}
70
</button>
71
))}
72
</Html>
73
</group>
74
);
75
}
76
```
77
78
### useGLTF
79
80
GLTF model loading hook with automatic disposal and type safety.
81
82
```typescript { .api }
83
/**
84
* GLTF model loading hook with automatic disposal
85
* @param path - Path to GLTF file
86
* @param useDraco - Use Draco compression, true
87
* @param useMeshOpt - Use MeshOpt compression, true
88
* @returns GLTF object with nodes, materials, and animations
89
*/
90
function useGLTF(path: string, useDraco?: boolean, useMeshOpt?: boolean): GLTF & ObjectMap;
91
92
interface GLTF {
93
animations: AnimationClip[];
94
scene: Group;
95
scenes: Group[];
96
cameras: Camera[];
97
asset: object;
98
}
99
100
interface ObjectMap {
101
nodes: { [name: string]: Object3D };
102
materials: { [name: string]: Material };
103
}
104
```
105
106
**Usage Examples:**
107
108
```typescript
109
import { useGLTF } from '@react-three/drei';
110
111
function Model({ path }) {
112
const { nodes, materials } = useGLTF(path);
113
114
return (
115
<group>
116
<mesh
117
geometry={nodes.Mesh.geometry}
118
material={materials.Material}
119
/>
120
</group>
121
);
122
}
123
124
// Preload models
125
useGLTF.preload('/model.glb');
126
```
127
128
### useTexture
129
130
Texture loading hook with multiple format support and automatic disposal.
131
132
```typescript { .api }
133
/**
134
* Texture loading hook with format support
135
* @param input - Texture path or array of paths
136
* @returns Texture or array of textures
137
*/
138
function useTexture(input: string | string[]): Texture | Texture[];
139
```
140
141
**Usage Examples:**
142
143
```typescript
144
import { useTexture } from '@react-three/drei';
145
146
function TexturedMesh() {
147
const texture = useTexture('/texture.jpg');
148
149
return (
150
<mesh>
151
<planeGeometry />
152
<meshStandardMaterial map={texture} />
153
</mesh>
154
);
155
}
156
157
// Multiple textures
158
function MultiTexturedMesh() {
159
const [colorMap, normalMap, roughnessMap] = useTexture([
160
'/color.jpg',
161
'/normal.jpg',
162
'/roughness.jpg'
163
]);
164
165
return (
166
<mesh>
167
<sphereGeometry />
168
<meshStandardMaterial
169
map={colorMap}
170
normalMap={normalMap}
171
roughnessMap={roughnessMap}
172
/>
173
</mesh>
174
);
175
}
176
177
// Preload textures
178
useTexture.preload('/texture.jpg');
179
```
180
181
### useFont
182
183
Font loading hook for text rendering with caching support.
184
185
```typescript { .api }
186
/**
187
* Font loading hook for text rendering
188
* @param path - Path to font JSON file
189
* @returns Font data object
190
*/
191
function useFont(path: string): FontData;
192
193
interface FontData {
194
data: any;
195
glyphs: { [key: string]: Glyph };
196
}
197
198
interface Glyph {
199
x: number;
200
y: number;
201
width: number;
202
height: number;
203
xAdvance?: number;
204
xOffset?: number;
205
yOffset?: number;
206
}
207
```
208
209
**Usage Examples:**
210
211
```typescript
212
import { useFont, Text3D } from '@react-three/drei';
213
214
function StyledText() {
215
const font = useFont('/fonts/helvetiker_regular.json');
216
217
return (
218
<Text3D font={font} size={1} height={0.2}>
219
3D Text
220
<meshNormalMaterial />
221
</Text3D>
222
);
223
}
224
225
// Preload fonts
226
useFont.preload('/fonts/helvetiker_regular.json');
227
```
228
229
### useEnvironment
230
231
Environment texture loading hook with preset support and HDRI loading.
232
233
```typescript { .api }
234
/**
235
* Environment texture loading hook with presets
236
* @param props - Environment loader configuration
237
* @returns Environment texture
238
*/
239
function useEnvironment(props: EnvironmentLoaderProps): Texture;
240
241
interface EnvironmentLoaderProps {
242
/** Environment preset name */
243
preset?: PresetsType;
244
/** Custom environment files */
245
files?: string | string[];
246
/** Environment path */
247
path?: string;
248
/** Texture encoding */
249
encoding?: TextureEncoding;
250
}
251
```
252
253
**Usage Examples:**
254
255
```typescript
256
import { useEnvironment } from '@react-three/drei';
257
258
function ReflectiveSphere() {
259
const envMap = useEnvironment({ preset: 'sunset' });
260
261
return (
262
<mesh>
263
<sphereGeometry />
264
<meshStandardMaterial
265
envMap={envMap}
266
metalness={1}
267
roughness={0}
268
/>
269
</mesh>
270
);
271
}
272
273
// Custom HDRI environment
274
function CustomEnvironment() {
275
const envMap = useEnvironment({
276
files: '/hdri/studio.hdr',
277
encoding: RGBEEncoding
278
});
279
280
return (
281
<mesh>
282
<torusGeometry />
283
<meshStandardMaterial envMap={envMap} />
284
</mesh>
285
);
286
}
287
```
288
289
### useAspect
290
291
Aspect ratio calculation hook for responsive design and viewport adaptation.
292
293
```typescript { .api }
294
/**
295
* Aspect ratio calculation hook for responsive design
296
* @param width - Target width
297
* @param height - Target height
298
* @param factor - Scale factor, 1
299
* @returns Scaled dimensions [width, height, 1]
300
*/
301
function useAspect(width: number, height: number, factor?: number): [number, number, number];
302
```
303
304
**Usage Examples:**
305
306
```typescript
307
import { useAspect } from '@react-three/drei';
308
309
function ResponsivePlane() {
310
const scale = useAspect(1920, 1080, 0.5);
311
312
return (
313
<mesh scale={scale}>
314
<planeGeometry />
315
<meshBasicMaterial />
316
</mesh>
317
);
318
}
319
320
// Dynamic aspect ratio
321
function DynamicAspect() {
322
const { viewport } = useThree();
323
const scale = useAspect(viewport.width, viewport.height, 0.8);
324
325
return (
326
<mesh scale={scale}>
327
<planeGeometry />
328
<meshBasicMaterial />
329
</mesh>
330
);
331
}
332
```
333
334
### useCamera
335
336
Camera access hook for getting the current scene camera.
337
338
```typescript { .api }
339
/**
340
* Camera access hook for getting current camera
341
* @returns Current camera object
342
*/
343
function useCamera(): Camera;
344
```
345
346
**Usage Examples:**
347
348
```typescript
349
import { useCamera } from '@react-three/drei';
350
351
function CameraInfo() {
352
const camera = useCamera();
353
354
useFrame(() => {
355
console.log('Camera position:', camera.position);
356
console.log('Camera rotation:', camera.rotation);
357
});
358
359
return null;
360
}
361
```
362
363
### useIntersect
364
365
Intersection detection hook for visibility and hover effects.
366
367
```typescript { .api }
368
/**
369
* Intersection detection hook for visibility effects
370
* @param onChange - Callback when visibility changes
371
* @returns Ref to attach to target object
372
*/
373
function useIntersect<T extends Object3D>(
374
onChange: (visible: boolean) => void
375
): React.RefObject<T>;
376
```
377
378
**Usage Examples:**
379
380
```typescript
381
import { useIntersect } from '@react-three/drei';
382
383
function VisibilityDetector() {
384
const [visible, setVisible] = useState(false);
385
const ref = useIntersect((isVisible) => setVisible(isVisible));
386
387
return (
388
<mesh ref={ref}>
389
<boxGeometry />
390
<meshStandardMaterial
391
color={visible ? 'green' : 'red'}
392
emissive={visible ? 'darkgreen' : 'darkred'}
393
/>
394
</mesh>
395
);
396
}
397
```
398
399
### useDepthBuffer
400
401
Depth buffer hook for accessing scene depth information.
402
403
```typescript { .api }
404
/**
405
* Depth buffer hook for accessing depth information
406
* @param options - Depth buffer configuration
407
* @returns Depth buffer texture and controls
408
*/
409
function useDepthBuffer(options?: {
410
size?: number;
411
frames?: number;
412
}): {
413
buffer: WebGLRenderTarget;
414
camera: Camera;
415
}
416
```
417
418
### useContextBridge
419
420
Context bridging hook for sharing React context across R3F boundaries.
421
422
```typescript { .api }
423
/**
424
* Context bridging hook for sharing React context
425
* @param contexts - Array of React contexts to bridge
426
* @returns Bridge component
427
*/
428
function useContextBridge(...contexts: React.Context<any>[]): React.ComponentType<{ children: React.ReactNode }>;
429
```
430
431
**Usage Examples:**
432
433
```typescript
434
import { useContextBridge } from '@react-three/drei';
435
436
const ThemeContext = React.createContext();
437
const UserContext = React.createContext();
438
439
function Scene() {
440
const ContextBridge = useContextBridge(ThemeContext, UserContext);
441
442
return (
443
<ContextBridge>
444
<mesh>
445
<ThemedMaterial />
446
</mesh>
447
</ContextBridge>
448
);
449
}
450
```
451
452
### useBoxProjectedEnv
453
454
Box-projected environment mapping hook for realistic interior reflections.
455
456
```typescript { .api }
457
/**
458
* Box-projected environment mapping hook
459
* @param envMap - Environment map texture
460
* @param position - Box position
461
* @param size - Box size
462
* @returns Box-projected environment uniforms
463
*/
464
function useBoxProjectedEnv(
465
envMap: Texture,
466
position: [number, number, number],
467
size: [number, number, number]
468
): {
469
envMap: Texture;
470
cubeMapSize: Vector3;
471
cubeMapPos: Vector3;
472
};
473
```
474
475
## Integration Patterns
476
477
### Animation Sequencing
478
479
```typescript
480
function AnimationSequence() {
481
const group = useRef();
482
const { actions } = useAnimations(animations, group);
483
const [currentAnimation, setCurrentAnimation] = useState('idle');
484
485
const playSequence = async () => {
486
await playAnimation('walk', 2000);
487
await playAnimation('run', 3000);
488
await playAnimation('idle', 1000);
489
};
490
491
const playAnimation = (name, duration) => {
492
return new Promise((resolve) => {
493
actions[name]?.reset().play();
494
setTimeout(resolve, duration);
495
});
496
};
497
498
return (
499
<group ref={group}>
500
<primitive object={scene} />
501
</group>
502
);
503
}
504
```
505
506
### Responsive Textures
507
508
```typescript
509
function ResponsiveTexture() {
510
const { viewport } = useThree();
511
const isMobile = viewport.width < 768;
512
513
const texture = useTexture(
514
isMobile ? '/textures/low-res.jpg' : '/textures/high-res.jpg'
515
);
516
517
return (
518
<mesh>
519
<planeGeometry />
520
<meshStandardMaterial map={texture} />
521
</mesh>
522
);
523
}
524
```
525
526
### Dynamic Environment Loading
527
528
```typescript
529
function DynamicEnvironment() {
530
const [preset, setPreset] = useState('sunset');
531
const envMap = useEnvironment({ preset });
532
533
useEffect(() => {
534
const handleTimeChange = () => {
535
const hour = new Date().getHours();
536
if (hour < 6) setPreset('night');
537
else if (hour < 12) setPreset('dawn');
538
else if (hour < 18) setPreset('city');
539
else setPreset('sunset');
540
};
541
542
handleTimeChange();
543
const interval = setInterval(handleTimeChange, 60000);
544
return () => clearInterval(interval);
545
}, []);
546
547
return (
548
<mesh>
549
<sphereGeometry />
550
<meshStandardMaterial envMap={envMap} />
551
</mesh>
552
);
553
}
554
```
555
556
### Performance Optimization
557
558
```typescript
559
// Preload assets for better performance
560
const preloadAssets = () => {
561
useGLTF.preload('/models/character.glb');
562
useTexture.preload(['/textures/diffuse.jpg', '/textures/normal.jpg']);
563
useFont.preload('/fonts/roboto.json');
564
};
565
566
// Call during app initialization
567
useEffect(preloadAssets, []);
568
569
// Automatic cleanup
570
function Model({ url }) {
571
const gltf = useGLTF(url);
572
573
// Automatic disposal on unmount
574
useEffect(() => {
575
return () => gltf.dispose?.();
576
}, [gltf]);
577
578
return <primitive object={gltf.scene} />;
579
}
580
```
581
582
### useDepthBuffer
583
584
Hook for creating and managing depth buffer textures.
585
586
```typescript { .api }
587
/**
588
* Creates and manages depth buffer textures for depth-based effects
589
* @param config - Depth buffer configuration
590
* @returns Depth texture
591
*/
592
function useDepthBuffer(config?: DepthBufferConfig): DepthTexture;
593
594
interface DepthBufferConfig {
595
/** Buffer size, 256 */
596
size?: number;
597
/** Update frames, Infinity */
598
frames?: number;
599
}
600
```
601
602
### useContextBridge
603
604
Hook for bridging React contexts across portals and different render trees.
605
606
```typescript { .api }
607
/**
608
* Bridges React contexts across portals and render trees
609
* @param contexts - React contexts to bridge
610
* @returns Context bridge component
611
*/
612
function useContextBridge(...contexts: Array<React.Context<any>>): React.ComponentType<{children: React.ReactNode}>;
613
```
614
615
### useBoxProjectedEnv
616
617
Hook for box-projected environment mapping on materials.
618
619
```typescript { .api }
620
/**
621
* Applies box-projected environment mapping to materials
622
* @param envMap - Environment map texture
623
* @param config - Box projection configuration
624
* @returns Box projection utilities
625
*/
626
function useBoxProjectedEnv(
627
envMap: Texture,
628
config: BoxProjectedEnvConfig
629
): BoxProjectedEnvResult;
630
631
interface BoxProjectedEnvConfig {
632
/** Environment map size */
633
envMapSize: [number, number, number];
634
/** Environment map position */
635
envMapPosition: [number, number, number];
636
}
637
638
interface BoxProjectedEnvResult {
639
/** Apply to material */
640
apply: (material: Material) => void;
641
}
642
```