What is difference between useState and useRef when use in R3F?

I want to know about difference using example.

useState triggers a re-render every time it changes — React re-evaluates and re-draws the component tree. useRef holds a mutable value that persists without causing any re-render when it changes.

In a 3D scene, this distinction is critical for performance. Animations run on every frame (60fps), so using useState for something like a rotation value would trigger 60 re-renders per second — very expensive. useRef lets you mutate values directly in the render loop without React overhead.Here’s a concrete R3F example showing both:

import { useRef, useState } from 'react'
import { useFrame } from '@react-three/fiber'

function Box() {
  const meshRef = useRef()         // Direct Three.js access — no re-render
  const [color, setColor] = useState('orange')  // Triggers re-render on change

  // useFrame runs every tick — useRef is safe here, useState would be costly
  useFrame(() => {
    meshRef.current.rotation.y += 0.01  // Direct mutation, no React overhead
  })

  return (
    <mesh
      ref={meshRef}
      onClick={() => setColor('hotpink')}  // useState: click changes color → re-render
    >
      <boxGeometry />
      <meshStandardMaterial color={color} />
    </mesh>
  )
}

Rule of thumb:

  • Use useRef for anything that changes every frame (rotation, position, animation values) — mutate it directly in useFrame.

  • Use useState for things that should visually update the React tree (color, visibility, UI state) — but keep these infrequent.

author: Claude; couldnt have explained it better:)

Thanks for answering my questions.