Now liveThe Skillselion MCP - thousands of ranked skills, loaded into your agent mid-task. No install.Get it →
openaec-foundation avatar

Threejs Impl React Three Fiber

  • 20 installs
  • 11 repo stars
  • Updated July 8, 2026
  • openaec-foundation/three.js-claude-skill-package

Helps with frontend development tasks.

About

threejs-impl-react-three-fiber is a Claude Code skill in the Frontend Development category.

  • threejs-impl-react-three-fiber
  • Frontend Development
  • AI-coding skill

Threejs Impl React Three Fiber by the numbers

  • 20 all-time installs (skills.sh)
  • +2 installs in the week ending Aug 4, 2026 (Skillselion tracking)
  • Ranked #1,562 of 2,245 Frontend Development skills by installs in the Skillselion catalog
  • Data as of Aug 4, 2026 (Skillselion catalog sync)
npx skills add https://github.com/openaec-foundation/three.js-claude-skill-package --skill threejs-impl-react-three-fiber

Add your badge

Show developers this skill is listed on Skillselion. Paste this into your README.

Listed on Skillselion
Installs20
repo stars11
Last updatedJuly 8, 2026
Repositoryopenaec-foundation/three.js-claude-skill-package

What it does

Helps with frontend development tasks.

Files

SKILL.mdMarkdownGitHub ↗

threejs-impl-react-three-fiber

Quick Reference

Canvas Component Props

PropTypeDefaultPurpose
gl`Renderer props \(canvas) => Renderer`{}
camera`Camera props \THREE.Camera`{ fov: 75, near: 0.1, far: 1000, position: [0,0,5] }
scene`Scene props \THREE.Scene`{}
shadows`boolean \ShadowMapType`false
raycasterRaycaster props{}Raycaster configuration
frameloop`"always" \"demand" \"never"`
resizeResizeOptions{ scroll: true, debounce: { scroll: 50, resize: 0 } }Resize behavior
orthographicbooleanfalseUse OrthographicCamera
dpr`number \[min, max]`[1, 2]
linearbooleanfalseLinear color space
flatbooleanfalseDisable tone mapping
legacybooleanfalseDisable color management
eventsEventManagerR3F defaultCustom event manager
eventSource`HTMLElement \React.RefObject`Parent node
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

  • references/methods.md -- Hook signatures and Canvas API
  • references/examples.md -- Working R3F code examples
  • references/anti-patterns.md -- What NOT to do with R3F

Official Sources

  • https://r3f.docs.pmnd.rs/
  • https://r3f.docs.pmnd.rs/api/canvas
  • https://r3f.docs.pmnd.rs/api/hooks
  • https://r3f.docs.pmnd.rs/api/events

Related skills

This week in AI coding

Five minutes, every Monday - the tools, releases and tactics for developers.

unsubscribe anytime.