r3f-best-practices

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

React Three Fiber Best Practices

React Three Fiber 最佳实践

Comprehensive guide for React Three Fiber and the Poimandres ecosystem. Contains 70+ rules across 12 categories, prioritized by impact.
这是针对React Three Fiber及Poimandres生态系统的全面指南,包含12个分类下的70+条规则,按影响优先级排序。

Sources & Credits

来源与致谢

Additional tips from 100 Three.js Tips by Utsubo
额外技巧来自Utsubo的100条Three.js技巧

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
在以下场景中可参考本指南:
  • 编写新的R3F组件
  • 优化R3F性能(重渲染是头号问题)
  • 正确使用Drei工具函数
  • 使用Zustand管理状态
  • 实现后期处理或物理效果

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
  • @react-three/fiber - Three.js的React渲染器
  • @react-three/drei - 实用的工具函数与抽象层
  • @react-three/postprocessing - 后期处理效果
  • @react-three/rapier - 物理引擎
  • zustand - 状态管理库
  • leva - 调试GUI

Rule Categories by Priority

按优先级划分的规则分类

PriorityCategoryImpactPrefix
1Performance & Re-rendersCRITICAL
perf-
2useFrame & AnimationCRITICAL
frame-
3Component PatternsHIGH
component-
4Canvas & SetupHIGH
canvas-
5Drei HelpersMEDIUM-HIGH
drei-
6Loading & SuspenseMEDIUM-HIGH
loading-
7State ManagementMEDIUM
state-
8Events & InteractionMEDIUM
events-
9Post-processingMEDIUM
postpro-
10Physics (Rapier)LOW-MEDIUM
physics-
11Leva (Debug GUI)LOW
leva-
优先级分类影响程度前缀
1性能与重渲染关键
perf-
2useFrame与动画关键
frame-
3组件模式
component-
4Canvas与初始化
canvas-
5Drei工具函数中高
drei-
6加载与Suspense中高
loading-
7状态管理
state-
8事件与交互
events-
9后期处理
postpro-
10物理效果(Rapier)中低
physics-
11Leva(调试GUI)
leva-

Quick Reference

快速参考

1. Performance & Re-renders (CRITICAL)

1. 性能与重渲染(关键)

  • 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
  • perf-visibility-toggle
    - Toggle visibility instead of remounting
  • perf-r3f-perf
    - Use r3f-perf for performance monitoring
  • perf-never-set-state-in-useframe
    - 绝不要在useFrame中调用setState
  • perf-isolate-state
    - 隔离需要React状态的组件
  • perf-zustand-selectors
    - 使用Zustand选择器,而非整个store
  • perf-transient-subscriptions
    - 对持续变化的值使用瞬态订阅
  • perf-memo-components
    - 对开销大的组件进行记忆化处理
  • perf-keys-for-lists
    - 为动态列表使用稳定的key
  • perf-avoid-inline-objects
    - 避免在JSX中创建对象/数组
  • perf-dispose-auto
    - 了解R3F的自动销毁行为
  • perf-visibility-toggle
    - 切换可见性而非重新挂载组件
  • perf-r3f-perf
    - 使用r3f-perf进行性能监控

2. useFrame & Animation (CRITICAL)

2. useFrame与动画(关键)

  • 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
  • frame-priority
    - 使用priority控制执行顺序
  • frame-delta-time
    - 动画中始终使用delta时间
  • frame-conditional-subscription
    - 不需要时禁用useFrame
  • frame-destructure-state
    - 仅解构所需的状态
  • frame-render-on-demand
    - 使用invalidate()实现按需渲染
  • frame-avoid-heavy-computation
    - 将繁重计算移到useFrame外部

3. Component Patterns (HIGH)

3. 组件模式(高)

  • 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
  • component-jsx-elements
    - 为Three.js对象使用JSX语法
  • component-attach-prop
    - 为非标准属性使用attach
  • component-primitive
    - 为已有对象使用primitive
  • component-extend
    - 为自定义类使用extend()
  • component-forwardref
    - 为可复用组件使用forwardRef
  • component-dispose-null
    - 对共享资源设置dispose={null}

4. Canvas & Setup (HIGH)

4. Canvas与初始化(高)

  • 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
  • canvas-size-container
    - Canvas填充父容器
  • canvas-camera-default
    - 通过props配置相机
  • canvas-gl-config
    - 配置WebGL上下文
  • canvas-shadows
    - 在Canvas层面启用阴影
  • canvas-frameloop
    - 选择合适的帧循环模式
  • canvas-events
    - 配置事件处理
  • canvas-linear-flat
    - 使用linear/flat保证颜色正确

5. Drei Helpers (MEDIUM-HIGH)

5. Drei工具函数(中高)

  • 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
  • drei-use-gltf
    - 结合预加载使用useGLTF
  • drei-use-texture
    - 使用useTexture加载纹理
  • drei-environment
    - 使用Environment实现真实光照
  • drei-orbit-controls
    - 使用Drei提供的OrbitControls
  • drei-html
    - 使用Html实现DOM叠加层
  • drei-text
    - 使用Text创建3D文本
  • drei-instances
    - 使用Instances实现优化的实例化渲染
  • drei-use-helper
    - 使用useHelper进行调试可视化
  • drei-bounds
    - 使用Bounds适配相机视角
  • drei-center
    - 使用Center居中对象
  • drei-float
    - 使用Float实现悬浮动画

6. Loading & Suspense (MEDIUM-HIGH)

6. 加载与Suspense(中高)

  • 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
  • loading-suspense
    - 将异步组件包裹在Suspense中
  • loading-preload
    - 使用useGLTF.preload预加载资源
  • loading-use-progress
    - 使用useProgress实现加载UI
  • loading-lazy-components
    - 懒加载繁重组件
  • loading-error-boundary
    - 处理加载错误

7. State Management (MEDIUM)

7. 状态管理(中)

  • 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
  • state-zustand-store
    - 创建聚焦的Zustand store
  • state-avoid-objects-in-store
    - 谨慎在store中存储Three.js对象
  • state-subscribeWithSelector
    - 细粒度订阅
  • state-persist
    - 需要时持久化状态
  • state-separate-concerns
    - 按关注点拆分store

8. Events & Interaction (MEDIUM)

8. 事件与交互(中)

  • 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
  • events-pointer-events
    - 在网格上使用指针事件
  • events-stop-propagation
    - 阻止事件冒泡
  • events-cursor-pointer
    - hover时改变光标
  • events-raycast-filter
    - 过滤射线检测
  • events-event-data
    - 了解事件数据结构

9. Post-processing (MEDIUM)

9. 后期处理(中)

  • 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
  • postpro-effect-composer
    - 使用EffectComposer
  • postpro-common-effects
    - 常用效果参考
  • postpro-selective-bloom
    - 使用SelectiveBloom实现优化的发光效果
  • postpro-custom-shader
    - 创建自定义效果
  • postpro-performance
    - 优化后期处理性能

10. Physics Rapier (LOW-MEDIUM)

10. 物理效果(Rapier)(中低)

  • 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
  • physics-setup
    - Rapier基础配置
  • physics-body-types
    - 动态、固定、运动学类型
  • physics-colliders
    - 选择合适的碰撞体
  • physics-events
    - 处理碰撞事件
  • physics-api-ref
    - 使用ref获取物理API
  • physics-performance
    - 优化物理效果性能

11. Leva (LOW)

11. Leva(低)

  • leva-basic
    - Basic Leva usage
  • leva-folders
    - Organize with folders
  • leva-conditional
    - Hide in production
  • leva-basic
    - Leva基础用法
  • leva-folders
    - 使用文件夹组织配置
  • leva-conditional
    - 生产环境中隐藏调试GUI

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
阅读单个规则文件获取详细说明与代码示例:
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
包含所有规则详细内容的完整指南:
../R3F_BEST_PRACTICES.md

Critical Patterns

关键模式

NEVER setState in useFrame

绝不要在useFrame中调用setState

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} />;
}
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

Zustand选择器

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;
});
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

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');
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

Suspense加载

jsx
function App() {
  return (
    <Canvas>
      <Suspense fallback={<Loader />}>
        <Model />
      </Suspense>
    </Canvas>
  );
}
jsx
function App() {
  return (
    <Canvas>
      <Suspense fallback={<Loader />}>
        <Model />
      </Suspense>
    </Canvas>
  );
}

r3f-perf Monitoring

r3f-perf性能监控

jsx
import { Perf } from 'r3f-perf';

function App() {
  return (
    <Canvas>
      <Perf position="top-left" />
      <Scene />
    </Canvas>
  );
}
jsx
import { Perf } from 'r3f-perf';

function App() {
  return (
    <Canvas>
      <Perf position="top-left" />
      <Scene />
    </Canvas>
  );
}

Toggle Visibility (Not Remounting)

切换可见性(而非重新挂载)

jsx
// BAD: Remounting destroys and recreates
{showModel && <Model />}

// GOOD: Toggle visibility, keeps instance alive
<Model visible={showModel} />
jsx
// BAD: Remounting destroys and recreates
{showModel && <Model />}

// GOOD: Toggle visibility, keeps instance alive
<Model visible={showModel} />