Complete collection of AI agent skills including: - Frontend Development (Vue, React, Next.js, Three.js) - Backend Development (NestJS, FastAPI, Node.js) - Mobile Development (React Native, Expo) - Testing (E2E, frontend, webapp) - DevOps (GitHub Actions, CI/CD) - Marketing (SEO, copywriting, analytics) - Security (binary analysis, vulnerability scanning) - And many more... Synchronized from: https://skills.sh/ Co-Authored-By: Claude <noreply@anthropic.com>
231 lines
7.2 KiB
Markdown
231 lines
7.2 KiB
Markdown
---
|
|
name: r3f-best-practices
|
|
description: 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.
|
|
license: MIT
|
|
metadata:
|
|
author: three-agent-skills
|
|
version: "1.0.0"
|
|
---
|
|
|
|
# React Three Fiber Best Practices
|
|
|
|
Comprehensive guide for React Three Fiber and the Poimandres ecosystem. Contains 60+ rules across 11 categories, prioritized by impact.
|
|
|
|
## 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 useFrame
|
|
- `perf-isolate-state` - Isolate components that need React state
|
|
- `perf-zustand-selectors` - Use Zustand selectors, not entire store
|
|
- `perf-transient-subscriptions` - Use transient subscriptions for continuous values
|
|
- `perf-memo-components` - Memoize expensive components
|
|
- `perf-keys-for-lists` - Use stable keys for dynamic lists
|
|
- `perf-avoid-inline-objects` - Avoid creating objects/arrays in JSX
|
|
- `perf-dispose-auto` - Understand R3F auto-dispose behavior
|
|
|
|
### 2. useFrame & Animation (CRITICAL)
|
|
|
|
- `frame-priority` - Use priority for execution order
|
|
- `frame-delta-time` - Always use delta for animations
|
|
- `frame-conditional-subscription` - Disable useFrame when not needed
|
|
- `frame-destructure-state` - Destructure only what you need
|
|
- `frame-render-on-demand` - Use invalidate() for on-demand rendering
|
|
- `frame-avoid-heavy-computation` - Move heavy work outside useFrame
|
|
|
|
### 3. Component Patterns (HIGH)
|
|
|
|
- `component-jsx-elements` - Use JSX for Three.js objects
|
|
- `component-attach-prop` - Use attach for non-standard properties
|
|
- `component-primitive` - Use primitive for existing objects
|
|
- `component-extend` - Use extend() for custom classes
|
|
- `component-forwardref` - Use forwardRef for reusable components
|
|
- `component-dispose-null` - Set dispose={null} on shared resources
|
|
|
|
### 4. Canvas & Setup (HIGH)
|
|
|
|
- `canvas-size-container` - Canvas fills parent container
|
|
- `canvas-camera-default` - Configure camera via prop
|
|
- `canvas-gl-config` - Configure WebGL context
|
|
- `canvas-shadows` - Enable shadows at Canvas level
|
|
- `canvas-frameloop` - Choose appropriate frameloop mode
|
|
- `canvas-events` - Configure event handling
|
|
- `canvas-linear-flat` - Use linear/flat for correct colors
|
|
|
|
### 5. Drei Helpers (MEDIUM-HIGH)
|
|
|
|
- `drei-use-gltf` - useGLTF with preloading
|
|
- `drei-use-texture` - useTexture for texture loading
|
|
- `drei-environment` - Environment for realistic lighting
|
|
- `drei-orbit-controls` - OrbitControls from Drei
|
|
- `drei-html` - Html for DOM overlays
|
|
- `drei-text` - Text for 3D text
|
|
- `drei-instances` - Instances for optimized instancing
|
|
- `drei-use-helper` - useHelper for debug visualization
|
|
- `drei-bounds` - Bounds to fit camera
|
|
- `drei-center` - Center to center objects
|
|
- `drei-float` - Float for floating animation
|
|
|
|
### 6. Loading & Suspense (MEDIUM-HIGH)
|
|
|
|
- `loading-suspense` - Wrap async components in Suspense
|
|
- `loading-preload` - Preload assets with useGLTF.preload
|
|
- `loading-use-progress` - useProgress for loading UI
|
|
- `loading-lazy-components` - Lazy load heavy components
|
|
- `loading-error-boundary` - Handle loading errors
|
|
|
|
### 7. State Management (MEDIUM)
|
|
|
|
- `state-zustand-store` - Create focused Zustand stores
|
|
- `state-avoid-objects-in-store` - Be careful with Three.js objects
|
|
- `state-subscribeWithSelector` - Fine-grained subscriptions
|
|
- `state-persist` - Persist state when needed
|
|
- `state-separate-concerns` - Separate stores by concern
|
|
|
|
### 8. Events & Interaction (MEDIUM)
|
|
|
|
- `events-pointer-events` - Use pointer events on meshes
|
|
- `events-stop-propagation` - Prevent event bubbling
|
|
- `events-cursor-pointer` - Change cursor on hover
|
|
- `events-raycast-filter` - Filter raycasting
|
|
- `events-event-data` - Understand event data structure
|
|
|
|
### 9. Post-processing (MEDIUM)
|
|
|
|
- `postpro-effect-composer` - Use EffectComposer
|
|
- `postpro-common-effects` - Common effects reference
|
|
- `postpro-selective-bloom` - SelectiveBloom for optimized glow
|
|
- `postpro-custom-shader` - Create custom effects
|
|
- `postpro-performance` - Optimize post-processing
|
|
|
|
### 10. Physics Rapier (LOW-MEDIUM)
|
|
|
|
- `physics-setup` - Basic Rapier setup
|
|
- `physics-body-types` - dynamic, fixed, kinematic
|
|
- `physics-colliders` - Choose appropriate colliders
|
|
- `physics-events` - Handle collision events
|
|
- `physics-api-ref` - Use ref for physics API
|
|
- `physics-performance` - Optimize physics
|
|
|
|
### 11. Leva (LOW)
|
|
|
|
- `leva-basic` - Basic Leva usage
|
|
- `leva-folders` - Organize with folders
|
|
- `leva-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
|
|
|
|
```jsx
|
|
// 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
|
|
|
|
```jsx
|
|
// 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
|
|
|
|
```jsx
|
|
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
|
|
|
|
```jsx
|
|
function App() {
|
|
return (
|
|
<Canvas>
|
|
<Suspense fallback={<Loader />}>
|
|
<Model />
|
|
</Suspense>
|
|
</Canvas>
|
|
);
|
|
}
|
|
```
|