Use Instances, useMemo, preload, lazy

Back to Modules

Optimization Techniques in React Three Fiber: useMemo, Instances, preload, lazy

React Three Fiber (R3F) leverages React's component-based structure to build 3D scenes with Three.js. To optimize performance and manage loading, several techniques are commonly employed, often utilizing React hooks and features from @react-three/drei.

useMemo for Performance Optimization

useMemo is a React hook that memoizes the result of a function call, preventing unnecessary re-renders and recalculations of expensive operations. In R3F, this is crucial for:

import React, { useMemo } from 'react';
import *s THREE from 'three';

function OptimizedBox() {
  const geom = useMemo(() => new THREE.BoxGeometry(), []);
  const mat = useMemo(() => new THREE.MeshBasicMaterial({ color: 'hotpink' }), []);

  return <mesh geometry={geom} material={mat} />;
}

Instances for Efficient Rendering of Many Objects

When rendering a large number of identical or similar objects, InstancedMesh in Three.js (and its R3F counterpart, <Instances> from @react-three/drei) is a powerful optimization. Instead of creating a separate mesh for each object, InstancedMesh renders multiple instances of the same geometry and material with different transformations (position, rotation, scale).

import { Instances, Instance } from '@react-three/drei';

function ManyBoxes() {
  return (
    <Instances limit={1000}>
      <boxGeometry />
      <meshBasicMaterial color="orange" />
      {Array.from({ length: 1000 }).map((_, i) => (
        <Instance key={i} position={[Math.random() * 10, Math.random() * 10, Math.random() * 10]} />
      ))}
    </Instances>
  );
}

preload and lazy for Asset and Component Loading

Lazy Loading Components with lazy and Suspense:

React's lazy and Suspense features allow you to defer loading of components until they are actually needed. This is particularly useful for R3F scenes or complex 3D models that might not be immediately visible, reducing the initial bundle size and improving perceived loading times.

import React, { Suspense, lazy } from 'react';
import { Canvas } from '@react-three/fiber';

const My3DScene = lazy(() => import('./My3DScene')); // My3DScene contains your R3F canvas and models

function App() {
  return (
    <div>
      <h1>My App</h1>
      <Suspense fallback={<div>Loading 3D Scene...</div>}>
        <Canvas>
          <My3DScene />
        </Canvas>
      </Suspense>
    </div>
  );
}

Preloading Assets with useGLTF.preload and useLoader:

For 3D models (especially glTF), textures, and other assets, preloading can improve the user experience by fetching assets in the background before they are displayed. @react-three/drei provides useGLTF.preload for glTF models.

import { useGLTF } from '@react-three/drei';

function Model({ url }) {
  const { scene } = useGLTF(url);
  return <primitive object={scene} />;
}

// Preload the model
useGLTF.preload('/path/to/your/model.gltf');