r3f-best-practices
React Three Fiber (R3F) and Poimandres ecosystem best practices. Use when writing, reviewing, or optimizing R3F code. Triggers on tasks involving @react-three/fiber, @react-three/drei, zustand, @react-three/postprocessing, @react-three/rapier, or leva.
How do I install this agent skill?
npx skills add https://github.com/emalorenzo/three-agent-skills --skill r3f-best-practicesIs this agent skill safe to install?
- Gen Agent Trust Hubpass
The skill is a comprehensive documentation set providing best practices for React Three Fiber (R3F) and the Poimandres ecosystem. It contains educational material on performance optimization, state management, and asset loading. No security risks, malicious patterns, or unauthorized activities were detected.
- Socketpass
No alerts
- Snykpass
Risk: LOW · No issues
- Runlayerpass
1/9 files flagged
- ZeroLeakspass
Score: 93/100 · 2 sections analyzed
What does this agent skill do?
React Three Fiber Best Practices
Comprehensive guide for React Three Fiber and the Poimandres ecosystem. Contains 70+ rules across 12 categories, prioritized by impact.
Sources & Credits
Additional tips from 100 Three.js Tips by Utsubo
When to Apply
Reference these guidelines when:
- Writing new R3F components
- Optimizing R3F performance (re-renders are the #1 issue)
- Using Drei helpers correctly
- Managing state with Zustand
- Implementing post-processing or physics
Ecosystem Coverage
- @react-three/fiber - React renderer for Three.js
- @react-three/drei - Useful helpers and abstractions
- @react-three/postprocessing - Post-processing effects
- @react-three/rapier - Physics engine
- zustand - State management
- leva - Debug GUI
Rule Categories by Priority
| Priority | Category | Impact | Prefix |
|---|---|---|---|
| 1 | Performance & Re-renders | CRITICAL | perf- |
| 2 | useFrame & Animation | CRITICAL | frame- |
| 3 | Component Patterns | HIGH | component- |
| 4 | Canvas & Setup | HIGH | canvas- |
| 5 | Drei Helpers | MEDIUM-HIGH | drei- |
| 6 | Loading & Suspense | MEDIUM-HIGH | loading- |
| 7 | State Management | MEDIUM | state- |
| 8 | Events & Interaction | MEDIUM | events- |
| 9 | Post-processing | MEDIUM | postpro- |
| 10 | Physics (Rapier) | LOW-MEDIUM | physics- |
| 11 | Leva (Debug GUI) | LOW | leva- |
Quick Reference
1. Performance & Re-renders (CRITICAL)
perf-never-set-state-in-useframe- NEVER call setState in useFrameperf-isolate-state- Isolate components that need React stateperf-zustand-selectors- Use Zustand selectors, not entire storeperf-transient-subscriptions- Use transient subscriptions for continuous valuesperf-memo-components- Memoize expensive componentsperf-keys-for-lists- Use stable keys for dynamic listsperf-avoid-inline-objects- Avoid creating objects/arrays in JSXperf-dispose-auto- Understand R3F auto-dispose behaviorperf-visibility-toggle- Toggle visibility instead of remountingperf-r3f-perf- Use r3f-perf for performance monitoring
2. useFrame & Animation (CRITICAL)
frame-priority- Use priority for execution orderframe-delta-time- Always use delta for animationsframe-conditional-subscription- Disable useFrame when not neededframe-destructure-state- Destructure only what you needframe-render-on-demand- Use invalidate() for on-demand renderingframe-avoid-heavy-computation- Move heavy work outside useFrame
3. Component Patterns (HIGH)
component-jsx-elements- Use JSX for Three.js objectscomponent-attach-prop- Use attach for non-standard propertiescomponent-primitive- Use primitive for existing objectscomponent-extend- Use extend() for custom classescomponent-forwardref- Use forwardRef for reusable componentscomponent-dispose-null- Set dispose={null} on shared resources
4. Canvas & Setup (HIGH)
canvas-size-container- Canvas fills parent containercanvas-camera-default- Configure camera via propcanvas-gl-config- Configure WebGL contextcanvas-shadows- Enable shadows at Canvas levelcanvas-frameloop- Choose appropriate frameloop modecanvas-events- Configure event handlingcanvas-linear-flat- Use linear/flat for correct colors
5. Drei Helpers (MEDIUM-HIGH)
drei-use-gltf- useGLTF with preloadingdrei-use-texture- useTexture for texture loadingdrei-environment- Environment for realistic lightingdrei-orbit-controls- OrbitControls from Dreidrei-html- Html for DOM overlaysdrei-text- Text for 3D textdrei-instances- Instances for optimized instancingdrei-use-helper- useHelper for debug visualizationdrei-bounds- Bounds to fit cameradrei-center- Center to center objectsdrei-float- Float for floating animation
6. Loading & Suspense (MEDIUM-HIGH)
loading-suspense- Wrap async components in Suspenseloading-preload- Preload assets with useGLTF.preloadloading-use-progress- useProgress for loading UIloading-lazy-components- Lazy load heavy componentsloading-error-boundary- Handle loading errors
7. State Management (MEDIUM)
state-zustand-store- Create focused Zustand storesstate-avoid-objects-in-store- Be careful with Three.js objectsstate-subscribeWithSelector- Fine-grained subscriptionsstate-persist- Persist state when neededstate-separate-concerns- Separate stores by concern
8. Events & Interaction (MEDIUM)
events-pointer-events- Use pointer events on meshesevents-stop-propagation- Prevent event bubblingevents-cursor-pointer- Change cursor on hoverevents-raycast-filter- Filter raycastingevents-event-data- Understand event data structure
9. Post-processing (MEDIUM)
postpro-effect-composer- Use EffectComposerpostpro-common-effects- Common effects referencepostpro-selective-bloom- SelectiveBloom for optimized glowpostpro-custom-shader- Create custom effectspostpro-performance- Optimize post-processing
10. Physics Rapier (LOW-MEDIUM)
physics-setup- Basic Rapier setupphysics-body-types- dynamic, fixed, kinematicphysics-colliders- Choose appropriate collidersphysics-events- Handle collision eventsphysics-api-ref- Use ref for physics APIphysics-performance- Optimize physics
11. Leva (LOW)
leva-basic- Basic Leva usageleva-folders- Organize with foldersleva-conditional- Hide in production
How to Use
Read individual rule files for detailed explanations and code examples:
rules/perf-never-set-state-in-useframe.md
rules/drei-use-gltf.md
rules/state-zustand-selectors.md
Full Compiled Document
For the complete guide with all rules expanded: ../R3F_BEST_PRACTICES.md
Critical Patterns
NEVER setState in useFrame
// BAD - 60 re-renders per second!
function BadComponent() {
const [position, setPosition] = useState(0);
useFrame(() => {
setPosition(p => p + 0.01); // NEVER DO THIS
});
return <mesh position-x={position} />;
}
// GOOD - Mutate refs directly
function GoodComponent() {
const meshRef = useRef();
useFrame(() => {
meshRef.current.position.x += 0.01;
});
return <mesh ref={meshRef} />;
}
Zustand Selectors
// BAD - Re-renders on ANY store change
const store = useGameStore();
// GOOD - Only re-renders when playerX changes
const playerX = useGameStore(state => state.playerX);
// BETTER - No re-renders, direct mutation
useFrame(() => {
const { value } = useStore.getState();
ref.current.position.x = value;
});
Drei useGLTF
import { useGLTF } from '@react-three/drei';
function Model() {
const { scene } = useGLTF('/model.glb');
return <primitive object={scene} />;
}
// Preload for instant loading
useGLTF.preload('/model.glb');
Suspense Loading
function App() {
return (
<Canvas>
<Suspense fallback={<Loader />}>
<Model />
</Suspense>
</Canvas>
);
}
r3f-perf Monitoring
import { Perf } from 'r3f-perf';
function App() {
return (
<Canvas>
<Perf position="top-left" />
<Scene />
</Canvas>
);
}
Toggle Visibility (Not Remounting)
// BAD: Remounting destroys and recreates
{showModel && <Model />}
// GOOD: Toggle visibility, keeps instance alive
<Model visible={showModel} />
How can the creator link this skill?
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/emalorenzo/three-agent-skills/r3f-best-practices">View r3f-best-practices on skillZs</a>