Skip to content
Agents tracked: 440 Downloads (7d): 202M down 19.5% GitHub stars: 10.4M Releases (7d): 607 Agent status: 3 with issuesSince last limit reset: Claude 28d · Codex 0d Updated Oct 21, 2026

Shadows in React Three Fiber

Shadows are off by default in three.js because they cost an extra render from the light's point of view. In React Three Fiber you turn them on in three places.

All React Three Fiber examples React Three Fiber: usage and stats

Shadows in React Three Fiber: screenshot of the example below running
The code below, running in Chromium on our server (Oct 12, 2026). Press Run to see it live and change it.

How it works

  1. Turn on the shadow map. The shadows prop on <Canvas> enables the renderer's shadow map. With true the docs say it uses PCFSoftShadowMap; you can also pass 'basic', 'percentage', 'soft' or 'variance'. [1]
  2. A light that casts. castShadow on the directional light. Props with a dash reach nested objects: shadow-mapSize sets light.shadow.mapSize (bigger is sharper and slower) and the shadow-camera-* props size the area the shadow covers. [2][3]
  3. Objects cast, the floor receives. Each mesh that should throw a shadow gets castShadow; the surface it falls on gets receiveShadow. A mesh can do both. [3]

Run and edit it

It runs in your browser, in a sandboxed frame that cannot see this site; the packages load from esm.sh only after you press Run.

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

function Spinner() {
  const ref = useRef()
  useFrame((state, delta) => {
    ref.current.rotation.x += delta * 0.6
    ref.current.rotation.y += delta * 0.8
  })
  return (
    <mesh ref={ref} position={[0, 1.4, 0]} castShadow>
      <torusKnotGeometry args={[0.6, 0.22, 128, 16]} />
      <meshStandardMaterial color="#2a78d6" roughness={0.4} />
    </mesh>
  )
}

export default function App() {
  return (
    // 1. shadows on: the renderer draws a shadow map
    <Canvas shadows camera={{ position: [3.5, 3.5, 5], fov: 45 }}>
      <color attach="background" args={['#ecebe6']} />
      <ambientLight intensity={0.6} />
      {/* 2. a light that casts shadows; mapSize and the shadow camera set quality and area */}
      <directionalLight
        position={[3, 6, 2]} intensity={2.5} castShadow
        shadow-mapSize={[2048, 2048]}
        shadow-camera-left={-4} shadow-camera-right={4}
        shadow-camera-top={4} shadow-camera-bottom={-4}
      />
      <Spinner />
      <mesh position={[-1.7, 0.4, 0.8]} castShadow>
        <boxGeometry args={[0.8, 0.8, 0.8]} />
        <meshStandardMaterial color="#eb6834" />
      </mesh>
      <mesh position={[1.6, 0.5, 0.9]} castShadow>
        <sphereGeometry args={[0.5, 32, 32]} />
        <meshStandardMaterial color="#1baf7a" />
      </mesh>
      {/* 3. the floor receives them */}
      <mesh rotation={[-Math.PI / 2, 0, 0]} receiveShadow>
        <planeGeometry args={[14, 14]} />
        <meshStandardMaterial color="#ffffff" />
      </mesh>
    </Canvas>
  )
}
Ctrl/⌘ + Enter runs

Free for signed-in members, with a daily limit. Describe the change in plain words; the new code runs only in your browser.

Shadows need three switches: shadows on the Canvas, castShadow on the light and the objects, receiveShadow on the floor. Code written by AgentGid [1].

Checked Oct 12, 2026: it starts without errors in Chromium with React Three Fiber 9.8.1, three.js 0.186.1, Drei 10.7.9, React 19.3.0. Needs WebGL.

More React Three Fiber examples

InstancedMesh in React Three Fiber useFrame in React Three Fiber onClick and pointer events in React Three Fiber OrbitControls in React Three Fiber

Sources

  1. Docs: Canvas (the shadows prop)
  2. Docs: Objects, properties and constructor arguments (dash-case props)
  3. three.js docs: DirectionalLightShadow

Explanations written by AgentGid from the official docs; the numbers in brackets point here. The code marked "written by AgentGid" is ours and free to copy.

Building something with React Three Fiber? Ask AgentGid →