threejs-react
Skill13 starsChanged 7 months agoMITView on GitHub
Integrates Three.js in React using React Three Fiber (R3F), @react-three/drei, and @react-three/postprocessing. Use when the user asks about Three.js in React, React Three Fiber, R3F, @react-three/drei, useFrame, useThree, Canvas setup, or 3D in React components. Trigger keywords: React Three Fiber, R3F, drei, useFrame, useThree, Canvas, 3D React, @react-three.
- Installs packages
We split this skill into the rules it gives an agent
1 rule. About 0 are common, 0 are distinctive, and 1 is very specific to this project.
≈0
Common · estimate
Many files like this have a rule of this kind.
≈0
Distinctive · estimate
This author's own choices. Worth a look.
1
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- Very specific: line 266
Always wrap useLoader components in <Suspense> or they'll throw
≈ “Common” is an estimate: at least 1 in 5 of the 308,232 skill files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.
Files
Three.js in React (React Three Fiber)
Install
npm install three @react-three/fiber @react-three/drei
npm install @react-three/postprocessing # optional, for post-processing
npm install @react-three/rapier # optional, for physicsCanonical Canvas Setup
import { Canvas } from "@react-three/fiber";
import { OrbitControls, Environment } from "@react-three/drei";
export default function App() {
return (
<Canvas
camera={{ position: [0, 2, 5], fov: 75 }}
shadows
gl={{
antialias: true,
toneMapping: THREE.ACESFilmicToneMapping,
toneMappingExposure: 1,
}}
>
<ambientLight intensity={0.5} />
<directionalLight position={[5, 10, 5]} intensity={1.5} castShadow />
<OrbitControls enableDamping />
<Environment preset="studio" />
<Box />
</Canvas>
);
}
function Box() {
const meshRef = useRef();
useFrame((state, delta) => {
meshRef.current.rotation.y += delta * 0.5;
});
return (
<mesh ref={meshRef} castShadow>
<boxGeometry args={[1, 1, 1]} />
<meshStandardMaterial color="royalblue" roughness={0.4} />
</mesh>
);
}Core Hooks
import { useFrame, useThree, useLoader } from "@react-three/fiber";
import { GLTFLoader } from "three/addons/loaders/GLTFLoader.js";
// useFrame — runs every frame, like requestAnimationFrame
// delta = seconds since last frame, state.clock.elapsedTime = total time
useFrame((state, delta) => {
meshRef.current.rotation.y += delta;
meshRef.current.position.y = Math.sin(state.clock.elapsedTime) * 0.5;
});
// useThree — access renderer, scene, camera, size
const { camera, renderer, scene, size } = useThree();
// useLoader — loads assets with Suspense
const gltf = useLoader(GLTFLoader, "/model.glb");
// Wrap component in <Suspense fallback={<Loading />}> in parent@react-three/drei Essentials
import {
OrbitControls, FlyControls, PointerLockControls,
PerspectiveCamera, OrthographicCamera,
Environment, Sky, Stars, Cloud,
useGLTF, useTexture, useFBO,
Text, Text3D, Billboard,
Box, Sphere, Plane, Torus, Cylinder,
RoundedBox, MeshDistortMaterial, MeshWobbleMaterial,
shaderMaterial, MeshReflectorMaterial,
Loader, Html, Stats,
Center, Float, Sparkles,
useProgress, useIntersect,
Instances, Instance,
BakeShadows, SoftShadows,
TransformControls, GizmoHelper, GizmoViewport,
} from '@react-three/drei';
// Common patterns:
<Environment preset="studio" /> // HDRI lighting — preset or files={[...]}
<Stats /> // FPS counter — dev only
<Html position={[0,1,0]}> // DOM in 3D space
<div>Hello World</div>
</Html>
<Text fontSize={0.5} color="white">Hello</Text>
<Float speed={2} floatIntensity={1}> {/* gentle bob animation */}
<mesh />
</Float>
<BakeShadows /> // freeze shadow map (static scenes)
<SoftShadows /> // PCF soft shadows helperLoading GLTF
import { useGLTF } from "@react-three/drei";
function Model() {
const { scene, animations } = useGLTF("/model.glb");
return <primitive object={scene} />;
}
// Preload before component mounts
useGLTF.preload("/model.glb");
// With DRACOLoader
import { useGLTF } from "@react-three/drei";
// drei handles DRACOLoader automatically when you use useGLTF
const { scene } = useGLTF("/model.glb"); // Draco supported by default via CDNAnimations with useAnimations
import { useGLTF, useAnimations } from "@react-three/drei";
function Character() {
const group = useRef();
const { scene, animations } = useGLTF("/character.glb");
const { actions } = useAnimations(animations, group);
useEffect(() => {
actions["walk"]?.reset().fadeIn(0.2).play();
return () => actions["walk"]?.fadeOut(0.2);
}, [actions]);
return <primitive ref={group} object={scene} />;
}Custom Shader Material with shaderMaterial
import { shaderMaterial } from "@react-three/drei";
import { extend } from "@react-three/fiber";
const WaveMaterial = shaderMaterial(
{ uTime: 0, uColor: new THREE.Color(0x4488ff) },
/* glsl */ `
uniform float uTime;
varying vec2 vUv;
void main() {
vUv = uv;
vec3 pos = position;
pos.y += sin(pos.x * 3.0 + uTime) * 0.1;
gl_Position = projectionMatrix * modelViewMatrix * vec4(pos, 1.0);
}
`,
/* glsl */ `
uniform vec3 uColor;
varying vec2 vUv;
void main() {
gl_FragColor = vec4(uColor, 1.0);
}
`,
);
extend({ WaveMaterial });
// Usage in JSX:
function WaveMesh() {
const matRef = useRef();
useFrame(({ clock }) => {
matRef.current.uTime = clock.elapsedTime;
});
return (
<mesh>
<planeGeometry args={[4, 4, 32, 32]} />
<waveMaterial ref={matRef} />
</mesh>
);
}Post-Processing
import {
EffectComposer,
Bloom,
SSAO,
ChromaticAberration,
} from "@react-three/postprocessing";
<Canvas>
{/* scene */}
<EffectComposer>
<Bloom luminanceThreshold={0.9} intensity={1.5} />
<SSAO radius={0.1} intensity={30} />
<ChromaticAberration offset={[0.002, 0.002]} />
</EffectComposer>
</Canvas>;Physics with @react-three/rapier
import { Physics, RigidBody, CuboidCollider } from "@react-three/rapier";
<Canvas>
<Physics gravity={[0, -9.81, 0]}>
<RigidBody>
<mesh castShadow>
<boxGeometry />
<meshStandardMaterial color="royalblue" />
</mesh>
</RigidBody>
<RigidBody type="fixed">
<mesh receiveShadow rotation={[-Math.PI / 2, 0, 0]}>
<planeGeometry args={[20, 20]} />
<meshStandardMaterial />
</mesh>
</RigidBody>
</Physics>
</Canvas>;Performance Tips
// Dispose unused resources
useEffect(() => {
return () => {
geo.dispose();
mat.dispose();
};
}, []);
// Memoize geometries and materials
const geo = useMemo(() => new THREE.SphereGeometry(1, 32, 16), []);
const mat = useMemo(
() => new THREE.MeshStandardMaterial({ color: "hotpink" }),
[],
);
// Instancing via drei
<Instances limit={1000}>
<sphereGeometry args={[0.1]} />
<meshStandardMaterial color="orange" />
{positions.map((p, i) => (
<Instance key={i} position={p} />
))}
</Instances>;Common Gotchas
useFrameruns outside React's render — don't callsetStateinside it (use ref)- Always wrap
useLoadercomponents in<Suspense>or they'll throw primitiveclones the scene graph — useclone()if you need multiple instancesextendmust be called before using custom JSX elements (<waveMaterial>)- Canvas fills its container — set container width/height, not the Canvas itself
useGLTFcaches by URL — same URL returns the same object (useclone()for multiple)
In this repository15 other files it gives its agents.
- AGENTS.mdAGENTS.md
- skills/llms.txtllms.txt
- threejs-animationSkill
- threejs-audioSkill
- threejs-cameraSkill
- threejs-coreSkill
- threejs-geometrySkill
- threejs-lightingSkill
- threejs-loadersSkill
- threejs-materialsSkill
- threejs-performanceSkill
- threejs-physicsSkill
- threejs-postprocessingSkill
- threejs-shadersSkill
- threejs-xrSkill
Does it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
No reviews yet
People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.
- It worked
- Partly
- It didn't
Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

