skillZs
★ LIVE SKILL TAGS ★
>>> LIVE SKILLS INDEX <<<
* OPEN SOURCE *
NO LOGIN, NO TRACKING
※ REAL INSTALL DATA ※
← back to all skills
impertio-studio/three.js-claude-skill-package128 installs

threejs-impl-react-three-fiber

Use when building 3D scenes with React using React Three Fiber (R3F). Prevents the common mistake of mixing imperative Three.js code with R3F's declarative model, creating objects inside useFrame, or forgetting Suspense for loaders. Covers Canvas, useFrame, useThree, useLoader, JSX mapping, event system, performance patterns. Keywords: React Three Fiber, R3F, Canvas, useFrame, useThree, useLoader, @react-three/fiber, 3D React, declarative Three.js, use Three.js with React, JSX 3D components.

How do I install this agent skill?

npx skills add https://github.com/impertio-studio/three.js-claude-skill-package --skill threejs-impl-react-three-fiber
view source ↗

Is this agent skill safe to install?

  • Gen Agent Trust Hubpass

    This skill provides educational documentation, API references, and best practices for using the React Three Fiber (R3F) library. It does not contain any executable code or malicious patterns.

  • Socketpass

    No alerts

  • Snykpass

    Risk: LOW · No issues

What does this agent skill do?

threejs-impl-react-three-fiber

Quick Reference

Canvas Component Props

PropTypeDefaultPurpose
glRenderer props | (canvas) => Renderer{}WebGL renderer config or factory
cameraCamera props | THREE.Camera{ fov: 75, near: 0.1, far: 1000, position: [0,0,5] }Default camera
sceneScene props | THREE.Scene{}Scene configuration
shadowsboolean | ShadowMapTypefalseEnable shadow maps
raycasterRaycaster props{}Raycaster configuration
frameloop"always" | "demand" | "never""always"Render loop strategy
resizeResizeOptions{ scroll: true, debounce: { scroll: 50, resize: 0 } }Resize behavior
orthographicbooleanfalseUse OrthographicCamera
dprnumber | [min, max][1, 2]Device pixel ratio
linearbooleanfalseLinear color space
flatbooleanfalseDisable tone mapping
legacybooleanfalseDisable color management
eventsEventManagerR3F defaultCustom event manager
eventSourceHTMLElement | React.RefObjectParent nodeEvent capture element
eventPrefixstring"offset"Coordinate prefix
onCreated(state: RootState) => void--Post-init callback
onPointerMissed(event: PointerEvent) => void--Click misses all meshes
fallbackReact.ReactNode--DOM fallback during init

Frameloop Modes

ModeBehavior
"always"ALWAYS renders every frame via requestAnimationFrame
"demand"ONLY renders when invalidate() is called -- use for static scenes
"never"NEVER renders automatically -- caller MUST invoke advance(timestamp)

Critical Warnings

NEVER create Three.js objects inside useFrame -- this allocates memory every frame and causes GC pressure. ALWAYS create objects outside the callback or use useMemo.

NEVER forget <Suspense> when using useLoader -- the component WILL suspend and crash without a Suspense boundary.

NEVER add the same Three.js object instance to the scene tree multiple times via <primitive> -- Three.js objects can only have one parent.

NEVER use useThree() without a selector when you only need one property -- the full state object triggers re-renders on every frame. ALWAYS use useThree((s) => s.camera).

NEVER mix imperative scene.add() calls with R3F's declarative JSX tree -- R3F manages the scene graph and imperative mutations cause desync.

ALWAYS use delta from useFrame for animations -- hardcoded time steps cause speed variations across different frame rates.

ALWAYS use useMemo for imperatively created geometries and materials -- without it, new objects are allocated on every render.


JSX-to-Three.js Mapping Rules

R3F uses deterministic conventions to translate JSX into Three.js scene graph operations:

  1. Lowercase JSX = Three.js class. <mesh /> creates new THREE.Mesh(). <meshStandardMaterial /> creates new THREE.MeshStandardMaterial().

  2. args = constructor arguments (array). <sphereGeometry args={[1, 32, 32]} /> becomes new THREE.SphereGeometry(1, 32, 32). When args changes, the object is destroyed and recreated.

  3. attach = parent property binding. <meshStandardMaterial attach="material" /> sets parent.material = this. Geometries auto-attach to "geometry", materials to "material".

  4. Dash-notation attach for nested paths. attach="shadow-camera" sets parent.shadow.camera = this. Array indexing: attach="material-0".

  5. Functional attach. attach={(parent, self) => { parent.add(self); return () => parent.remove(self); }} for custom bind/unbind.

  6. Properties with .set() accept shorthand. position={[1, 2, 3]} calls object.position.set(1, 2, 3). color="hotpink" calls object.color.set("hotpink").

  7. Scalar shorthand. scale={2} calls object.scale.setScalar(2).

  8. Dash-case pierces nested properties. rotation-x={Math.PI} sets object.rotation.x = Math.PI.


Hooks

useFrame

useFrame((state: RootState, delta: number, xrFrame?: XRFrame) => void, priority?: number)

Subscribes a callback to the render loop. Executes every frame.

State object key properties:

PropertyTypeDescription
glTHREE.WebGLRendererThe renderer
sceneTHREE.SceneThe scene
cameraTHREE.CameraActive camera
clockTHREE.ClockSystem clock
pointerTHREE.Vector2Normalized pointer (-1 to +1)
size{ width, height, top, left }Canvas dimensions (px)
viewport{ width, height, factor, distance, aspect }Camera-relative metrics
invalidate() => voidRequest render in demand mode
advance(timestamp: number) => voidAdvance one tick in never mode
performance{ current, min, max, regress() }Adaptive performance
set(state) => voidMutate state directly
get() => RootStateRead state non-reactively

Priority system: Callbacks execute in ascending priority order. When ANY callback has priority > 0, R3F disables automatic renderer.render(). The highest-priority subscriber MUST call state.gl.render(state.scene, state.camera) manually. Negative priorities do NOT disable auto-rendering.

useThree

const state = useThree()                              // full state (re-renders often)
const camera = useThree((state) => state.camera)      // selector (re-renders only on change)

Returns the RootState (same object as useFrame's state). ALWAYS use a selector when only one property is needed.

useLoader

const result = useLoader(LoaderClass, url, extensions?, onProgress?)
const results = useLoader(LoaderClass, [url1, url2], extensions?)

Suspense-based asset loading. ALWAYS wrap in <Suspense fallback={...}>.

  • Assets are cached by URL -- loading the same URL twice returns the cached result.
  • useLoader.preload(LoaderClass, url) preloads before component mount.
  • GLTF results include { nodes, materials, scene, animations }.

useGraph

const { nodes, materials } = useGraph(object3D)

Traverses an Object3D hierarchy and returns memoized { nodes, materials } collections keyed by name.


Primitives and extend()

Primitives

Insert pre-existing Three.js objects into the declarative tree:

<primitive object={existingMesh} position={[10, 0, 0]} />
  • NEVER add the same object instance multiple times -- Three.js objects can have only one parent.
  • Primitives do NOT auto-dispose; the caller MUST manage lifecycle.

extend()

Register custom Three.js classes as JSX elements:

import { extend } from '@react-three/fiber'
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls'

extend({ OrbitControls })
// Now usable as <orbitControls args={[camera, domElement]} />

The JSX element name is the camelCase version of the registered key.


Event System

R3F implements pointer events via raycasting. Events bubble through the scene graph.

Supported Events

EventTrigger
onClickPointer click on mesh
onContextMenuRight-click / context menu
onDoubleClickDouble click
onPointerUpPointer released
onPointerDownPointer pressed
onPointerOverPointer enters mesh (fires continuously)
onPointerOutPointer leaves mesh
onPointerEnterPointer enters mesh (fires once)
onPointerLeavePointer leaves mesh (fires once)
onPointerMovePointer moves over mesh
onPointerMissedClick hits no mesh (Canvas-level)
onWheelScroll wheel
onUpdateObject receives new props

Event Object Properties

PropertyTypeDescription
objectTHREE.Object3DThe mesh actually hit
eventObjectTHREE.Object3DObject with the event handler
pointTHREE.Vector3Intersection in world space
distancenumberCamera-to-intersection distance
uvTHREE.Vector2UV coordinates at intersection
faceTHREE.FaceIntersected face
rayTHREE.RayRay used for intersection
cameraTHREE.CameraActive camera
intersectionsIntersection[]All intersected objects
deltanumberPixel distance down-to-up
sourceEventEventOriginal DOM event
stopPropagation()functionPrevent bubbling to occluded objects

Performance Patterns

Disposal

  • R3F ALWAYS calls dispose() on Three.js objects when components unmount, freeing GPU resources.
  • Set dispose={null} on an element to PREVENT auto-disposal -- use when objects are shared across components.

Static Scenes

Use frameloop="demand" with invalidate() for scenes that do not animate continuously (dashboards, configurators). This saves GPU cycles.

Portals

import { createPortal } from '@react-three/fiber'

createPortal(children, targetScene)

Renders children into a different scene/layer without affecting the main scene graph.

useMemo for Imperative Objects

ALWAYS wrap imperatively created geometries and materials in useMemo:

const geometry = useMemo(() => new THREE.TorusKnotGeometry(1, 0.3, 128, 32), [])

Without useMemo, a new object is created on every render.


Reference Links

Official Sources

Add the canonical catalog link to the repository README so users can inspect current installs and available audits. The publishing guide covers the complete discovery path.

<a href="https://skillzs.dev/skills/impertio-studio/three.js-claude-skill-package/threejs-impl-react-three-fiber">View threejs-impl-react-three-fiber on skillZs</a>