L’interface est localisée ; les présentations et documents des Skills sont traduits automatiquement par IA dans votre langue. Le code, les commandes, chemins et termes techniques restent en version originale, et le document de l’auteur fait foi.
Explorer les Skills
Productivité · SKILL.md

react-three-fiber

react-three-fiber

Builds 3D scenes in React with React Three Fiber (R3F), a React renderer for Three.js where meshes, lights and cameras are JSX components. Use when a user asks to add a 3D scene to a React or Next.js site, build a product configurator, load a GLTF model, animate with useFrame, handle click and hover on 3D objects, or speed up a slow R3F scene.

Independent GitHub snapshot · Automated classification · Original documentation governs

Tterminalskills / skillsApache-2.0

Documentation de la Skill

GitHub

name: react-three-fiber description: >- Builds 3D scenes in React with React Three Fiber (R3F), a React renderer for Three.js where meshes, lights and cameras are JSX components. Use when a user asks to add a 3D scene to a React or Next.js site, build a product configurator, load a GLTF model, animate with useFrame, handle click and hover on 3D objects, or speed up a slow R3F scene. license: Apache-2.0 compatibility: 'R3F 9.x needs React 19 and three 0.156 or newer; drei 10.x pairs with R3F 9. React 18 projects use R3F 8 and drei 9.' metadata: author: terminal-skills version: "1.1.0" category: development tags: - 3d - webgl - react - threejs - r3f repository: https://github.com/pmndrs/react-three-fiber

React Three Fiber — Declarative Three.js for React

Overview

React Three Fiber (R3F) is a React renderer for Three.js. You write scenes as JSX (<mesh>, <boxGeometry>, <meshStandardMaterial>), and props map straight onto Three.js object properties. Hooks, state, Suspense and context work as in any React app, and everything in the Three.js ecosystem stays available. @react-three/drei adds ready-made helpers (controls, loaders, environment maps, text, HTML overlays).

Current versions: @react-three/fiber 9.8, @react-three/drei 10.7, three 0.186. R3F 9 requires React 19; with React 18 install @react-three/fiber@8 and @react-three/drei@9.

Instructions

Install

npm install three @react-three/fiber @react-three/drei
npm install -D @types/three                 # TypeScript
npm install @react-three/postprocessing     # optional: bloom, depth of field, etc.

In Next.js, components that render a <Canvas> must be client components ('use client'). If a Three.js add-on ships untranspiled code, add transpilePackages: ['three'] to next.config.js.

Canvas and scene

'use client'
import { Canvas } from '@react-three/fiber'
import { OrbitControls, Environment } from '@react-three/drei'

export default function Scene() {
  return (
    <Canvas camera={{ position: [0, 2, 5], fov: 50 }} dpr={[1, 2]} shadows>
      <ambientLight intensity={0.4} />
      <directionalLight position={[5, 5, 5]} castShadow />
      <mesh position={[0, 1, 0]} castShadow>
        <boxGeometry args={[1, 1, 1]} />
        <meshStandardMaterial color="orange" />
      </mesh>
      <mesh rotation={[-Math.PI / 2, 0, 0]} receiveShadow>
        <planeGeometry args={[10, 10]} />
        <meshStandardMaterial color="#444" />
      </mesh>
      <OrbitControls />
      <Environment preset="city" />
    </Canvas>
  )
}

Canvas fills its parent, so give the parent a height. Defaults: dpr [1, 2], sRGB output and ACES filmic tone mapping, a translucent WebGL renderer with antialiasing. Pass fallback={<p>WebGL is not available</p>} for devices without WebGL.

Animation with useFrame

import { useRef } from 'react'
import { useFrame } from '@react-three/fiber'
import * as THREE from 'three'

function SpinningBox() {
  const meshRef = useRef<THREE.Mesh>(null)
  useFrame((state, delta) => {
    if (!meshRef.current) return
    meshRef.current.rotation.y += delta                       // frame-rate independent
    meshRef.current.position.x = THREE.MathUtils.lerp(
      meshRef.current.position.x, state.pointer.x * 2, 0.1,   // pointer is -1..1; state.mouse is deprecated
    )
  })
  return (
    <mesh ref={meshRef}>
      <boxGeometry />
      <meshStandardMaterial color="hotpink" />
    </mesh>
  )
}

Mutate refs inside useFrame; never call setState there. useThree() returns the renderer, scene, camera, viewport and size.

Loading models

import { Suspense, useEffect } from 'react'
import { useGLTF, useAnimations } from '@react-three/drei'

function Character({ animation = 'idle' }: { animation?: string }) {
  const { scene, animations } = useGLTF('/models/character.glb')
  const { actions } = useAnimations(animations, scene)
  useEffect(() => {
    actions[animation]?.reset().fadeIn(0.3).play()
    return () => { actions[animation]?.fadeOut(0.3) }
  }, [animation, actions])
  return <primitive object={scene} scale={1.5} />
}
useGLTF.preload('/models/character.glb')

// <Canvas><Suspense fallback={null}><Character /></Suspense></Canvas>

useGLTF decodes Draco-compressed files out of the box. To get a typed JSX component for a model and a compressed copy, run npx gltfjsx model.glb --transform --types; it writes model-transformed.glb (Draco, resized webp textures, pruned) and a component.

Events

import { useState } from 'react'

function InteractiveBox() {
  const [hovered, setHovered] = useState(false)
  const [active, setActive] = useState(false)
  return (
    <mesh
      scale={active ? 1.5 : 1}
      onClick={(e) => { e.stopPropagation(); setActive(!active) }}
      onPointerOver={() => setHovered(true)}
      onPointerOut={() => setHovered(false)}
    >
      <boxGeometry />
      <meshStandardMaterial color={hovered ? 'hotpink' : 'orange'} />
    </mesh>
  )
}

R3F raycasts pointer events onto meshes. Use e.stopPropagation() so objects behind the hit do not also fire, and onPointerMissed on Canvas for clicks on empty space.

Rendering only when needed

<Canvas frameloop="demand">…</Canvas>
// elsewhere: const invalidate = useThree((s) => s.invalidate); invalidate()

With frameloop="demand" a frame is drawn only when props change or invalidate() is called; useful for static configurators on laptops and phones.

Examples

Example 1: Product viewer in a Next.js page

User prompt: "Show our sneaker.glb on the product page, let people rotate it, and keep the page fast."

Create a 'use client' component with <Canvas frameloop="demand" camera={{ position: [0, 0, 3] }}>, wrap a <Stage> or <Environment preset="studio" /> plus <OrbitControls makeDefault /> and a <Suspense fallback={null}> around the model. Run npx gltfjsx public/sneaker.glb --transform --types first and use sneaker-transformed.glb. Result: a draggable model that renders frames only while the user interacts, with the file typically 70-90% smaller.

Example 2: Thousands of identical objects

User prompt: "Our star field with 5,000 meshes drops to 15 fps. Fix it."

Replace the 5,000 <mesh> elements with one <Instances limit={5000}> (from drei) holding a shared geometry and material, and render each star as <Instance position={…} />; for pure animation use a single <instancedMesh args={[undefined, undefined, 5000]}> and update matrices in useFrame. Result: one draw call instead of 5,000, and the frame rate recovers.

Guidelines

  • Everything lives inside <Canvas>; DOM elements go outside, or inside it through drei's <Html>.
  • Do not use requestAnimationFrame or React state for per-frame values; use useFrame with refs.
  • Create geometry, materials and vectors once (module scope or useMemo), not on every render or frame.
  • Wrap loaders in <Suspense>; useGLTF, useTexture and useLoader suspend and cache by URL. R3F disposes objects when they unmount, so do not dispose shared cached assets by hand.
  • Use <AdaptiveDpr> and <PerformanceMonitor> from drei to lower resolution on slow devices.
  • Colours and textures are colour-managed (sRGB) by default; set flat to drop tone mapping, linear to drop colour conversion, only when you know why.
  • args on a geometry or object are constructor arguments; changing them recreates the object, so animate properties instead.
  • R3F can render with THREE.WebGPURenderer through an async gl factory (see the Canvas docs), but treat it as advanced.
  • For plain, non-React 3D use Three.js directly; for physics add @react-three/rapier.
Skills enregistrées