pmndrs/react-three-fiber
 Watch   
 Star   
 Fork   
16 days ago
react-three-fiber

v9.8.1

The main changes here are bug fixes:

  • Activity now works completely inside of R3F, even across boundaries with React DOM. Ie, an Activity that wraps the Canvas.
  • In some cases a renderer would not be disposed when the Canvas was unmounted. This is fixed and we clarify in which instances we auto-dispose.

What's Changed

New Contributors

Full Changelog: https://github.com/pmndrs/react-three-fiber/compare/v9.8.0...v9.8.1

18 days ago
react-three-fiber

v9.8.0

The headline feature is that R3F is now compatible with React 19.3.0. We don't fully support all of the new APIs, but it will not longer conflict to run the latest and greatest React.

In addition we fixed some long standing bugs:

  • React roots are configured synchronously and then gated on the renderer if it need async, for example with WebGPURenderer. This means that you won't get awkward out of sync issues.
  • Strict Mode no longer causes problems for our canvas. This was related to the async support added a while ago as well.

Have fun!

What's Changed

New Contributors

Full Changelog: https://github.com/pmndrs/react-three-fiber/compare/v9.7.0...v9.8.0

2026-09-08 14:07:16
react-three-fiber

v10.0.0-alpha.5

Alpha 5 is a types release. The WebGPU resource hooks now carry three's exact node generics, the stale TSL augmentations are gone, and the built declarations are compiled by a strict consumer fixture on every build. Alongside it: the reconciler oddities that strict-TypeScript consumers surfaced while working around the old types, and the single-canvas depth-attachment fix.

Types

  • useUniform and useUniforms keep three's exact UniformNode<TNodeType, TValue> generics and the input's exact keys. A number uniform is a Node<'float'>, so TSL math, mix() and bloom() accept it without a cast; .value is typed; an unknown key is an error (#3769, #3886, #3887).
  • ScopedStore distinguishes nested scopes from object-valued and callable (Fn()) leaves at runtime, and .scope(key) accepts an explicit schema generic for cross-call access.
  • The stale ShaderNodeObject and three/tsl Fn augmentations are gone. three's own Fn overloads, including the Fn(fn, 'void') statement-call form compute kernels use, are reachable again with R3F installed.
  • Matrix2 is an accepted uniform value (mat2), matching three's uniform() overloads.
  • StorageLike includes Storage3DTexture and StorageArrayTexture, so useGPUStorage accepts what compute.mdx documents.
  • once() is typed as the value the prop declares: translate={once(0, 0, 5)} and center={once()} typecheck without a cast.
  • On the /webgpu entry, Canvas's onCreated receives WebGPURootState, so WebGPU-only renderer members no longer need an instanceof narrow.
  • pnpm verify-types compiles a strict consumer fixture against the built declarations with skipLibCheck: false, for every entry.
  • Reader-mode useUniforms, useNodes, useBuffers and useGPUStorage accept an explicit schema: useUniforms<{ blurAmount: number }>() returns typed nodes for values registered elsewhere, instead of UniformNode<unknown>.
  • extend(THREE) accepts a whole module namespace without a cast; only its constructors are registered.
  • raycaster={{ params: { Points: { threshold: 0.2 } } }} typechecks: params is a partial, matching the runtime merge into the raycaster's defaults.
  • eventSource accepts any DOM Element, so an SVGRenderer's <svg> no longer needs a cast.
  • <primitive> keeps typed pointer events (onClick={(e) => ...} infers e) and accepts arbitrary props for the wrapped object.
  • The examples compile under strict TypeScript without a single as unknown as cast; the remaining as any sites are third-party gaps (three's Backend, @use-gesture) and are commented as such.

Bug Fixes

  • useTexture's onLoad receives the keyed record for record inputs, matching its declared type. It was handed useLoader's positional array, so textures.map.wrapT threw at runtime.
  • Prefixed elements (<threeLine>) no longer throw "ThreeLine is not part of the THREE namespace" on their first prop update.
  • A removed prop resets to the class default for every class. Any class whose constructor takes arguments (every material, geometry and camera) previously had the prop set to 0, turning a removed color black.
  • fromRef(ref, transform) maps the resolved sibling before assignment, so props that need the sibling wrapped are declarative: lightsNode={fromRef(lightRef, (l) => lights([l]))}.
  • Six-file .hdr cube sets load through HDRCubeTextureLoader in useEnvironment, <Environment> and the Canvas background prop, with linear color space.
  • A lone primary <Canvas id> owns the renderer's default canvas target, so its depth attachment follows the layout instead of the element's construction size (#3905).
  • Canvas honors the resize.debounce prop after the initial measurement (#3881).
  • useRenderPipeline callbacks receive a WebGPURenderer-typed state, may not return the hook-owned scenePass, and the hook's return narrows renderPipeline on isReady (#3901).
  • The Pointcloud example's fragment shader handles point colors correctly.

Examples

  • The demo registry is the one table of contents; the app derives its groups from it. Adds WebGPUFog and WebGPUPrimaryOnly, drops stale entries, and the examples cleanup from #3883.

eslint-plugin

  • no-clone-in-loop only flags .clone() calls. A loop variable named clone used as clone.position no longer trips it.
2026-08-24 20:32:50
react-three-fiber

v10.0.0-alpha4

We have been hard at work on the pmndrs org and all the while alpha updates have been streaming in for R3F v10 as we march toward first class WebGPU and TSL support. Let's catch you up on the big news:

Improved TSL workflow

The original v10 alpha introduced useUniforms, useNodes, and useLocalNodes. We have experimented with more hooks since then.

  • New experimental useBuffers and useGPUStorage hooks manage compute buffers and storage textures.
  • useTextures provides a reactive, ref-counted texture registry without passing refs throughout the component tree.
  • TSL nodes, uniforms, buffers, and storage now rebuild atomically during fast refresh instead of requiring a full reload.
  • useRenderPipeline replaces usePostProcessing and provides declarative render-pipeline and MRT setup.
  • Imports from @react-three/fiber/webgpu now type useThree and useFrame against WebGPURenderer state without manual casts.

The scheduler gets its own repo

What started as a revamp of the internal R3F scheduler has split out into its own project that is intended to stand on its own legs: https://github.com/pmndrs/scheduler

  • useFrame can run outside , making the scheduler useful for external UI and application systems.
  • Named phases, explicit before/after ordering, FPS limits, and render takeover make complex frame loops easier to compose.
  • Every Canvas now owns its frameloop, invalidation, and manual stepping. A demand-driven Canvas can no longer interfere with an always-running sibling for real multi-canvas support.

Multiple canvases

WebGPU canvases can now share a single renderer and GPU context. This unlocks HUDs, picture-in-picture views, multi-viewport rendering, and 3D layers separated by regular HTML.

<Canvas id="main" renderer>
  <MainScene />
</Canvas>

<Canvas
  renderer={{
    primaryCanvas: 'main',
    scheduler: { after: 'main', fps: 30 },
  }}>
  <Hud />
</Canvas>

Each Canvas keeps its own scene, camera, events, and state while sharing the renderer and GPU resources. The scheduler handles target switching, render order, and independent frame rates.

More stuff!

There are also several smaller features that remove common imperative work:

  • Canvas accepts declarative background colors, environment files, and presets.
  • Explicit width and height props make fixed-resolution rendering and video export straightforward.
  • The default camera is part of the scene graph, so camera-attached lights, meshes, and HUD elements render naturally.
  • fromRef() connects props to sibling refs without a mount effect.
  • once() supports mount-only geometry and object methods.
  • userData.interactivePriority lets overlays and controls take precedence over distance-based hit testing.

And then the usual hardening and bug fixes. There are a lot of ideas being tried out here so as always we would appreciate feedback on what is working and what is not working.

Try it out with:

npm install @react-three/fiber@alpha

Cheers!

What's Changed

New Contributors

Full Changelog: https://github.com/pmndrs/react-three-fiber/compare/v10.0.0-alpha.1...v10.0.0-alpha.4

2026-08-01 00:11:23
react-three-fiber

v9.7.0

The headline updates for this release are the reconciler fixes. We did a pass to harden what is there against react-dom as the standard.

  • R3F's internal children were not being reordered correctly. Basically, if React reordered children, our internal map would drift out of sync and this would cause subtle bugs. This is now fixed. Thanks to @kvvasuu who reported it and @wanxiankai who offered a solution.
  • Pierced props now reset properly. We had a bug where if a pierce prop was unset, the reconciler would try to reset it to a default value. However, it would set it to the base object instead of the pierced prop. This is fixed now.
// Initial render
<mesh position-x={5} />

// Later render: prop removed
<mesh />

// bug: would set it to the base object
mesh.x = 0 // !!! 
  • Host props now update properly. Host props are ones that we supply such as dispose and onUpdate. These now update properly. This also caused a subtle bug where imperatively updated values could get overwritten unexpectedly after unsetting the value in React. This is all fixed. Note: attach is fixed on first set and ignored if you try to dynamically update it.
  • Properly batch instance reconstruction. This one is pretty technical and if you are curious check out the test in the attached PR. Basically, there was an edge case where if two instances needed to reconstruct (because the args updated), one could be ignore if the other bailed out of updates because of a React.memo or similar. It is likely a problem you never had, but your agent would curse if you did.
  • Event priorities match react-dom. React allows for prioritizing events, for example continuous events like wheel get a higher priority over impulse events like pointer. We copy from the best here and use the same list react-dom does.
  • Support reconciler microtasks. The React reconciler has a cool feature where it can queue microtasks to defer work based on the priorities we set earlier.

What's Changed

New Contributors

Full Changelog: https://github.com/pmndrs/react-three-fiber/compare/v9.6.1...v9.7.0

2026-04-29 04:04:31
react-three-fiber

v9.6.1

What's Changed

Full Changelog: https://github.com/pmndrs/react-three-fiber/compare/v9.6.0...v9.6.1

2026-04-14 01:42:27
react-three-fiber

v9.6.0 - Sunset X

Ever tried using <shaderMaterial uniforms={{ time: { value: time } }} /> and ran into immediate issues with desync? No more.

The uniforms objects on ShaderMaterial and its derivatives now have a stable reference. Objects passed into uniforms will instead copy into it. This is the same as behavior for math structures that have copy such as position, rotation, quaternion, etc. and ends up simplifying using the raw JSX where utilities were often introduced before.

Documentation can be found here: https://r3f.docs.pmnd.rs/api/objects#shader-material-uniforms

And an example can be found here: https://github.com/pmndrs/react-three-fiber/blob/master/example/src/demos/ShaderMaterial.tsx

What's Changed

New Contributors

Full Changelog: https://github.com/pmndrs/react-three-fiber/compare/v9.5.0...v9.6.0

2026-01-17 13:58:54
react-three-fiber

v10.0.0-alpha.1

A New Era

R3F v10 has been a long time coming. We have talked over plans for years but late last year @DennisSmolek took the initiative do it all himself. We now have an alpha release, along with an alpha release of Drei 11. You can try it out today.

npm install @react-three/fiber@alpha

We were so excited to get this out we forgot to make a release for alpha.0 and alpha.1 is already upon us. But let's quickly get you caught up on what you can expect to be new.

  • R3F now supports the WebGLRenderer and WebGPURenderer. This means state.gl is now state.renderer.
  • There is a new scheduler, allowing for useFrame to have advanced scheduling and also allows for it to be used outside of <Canvas />. Read more here: Frame Loop Overview.
  • WebGPU and TSL is first-class, with new built-ins just for working with TSL: useUniforms, useNodes, useLocalNodes and usePostProcessing. Read more here: WebGPU Hook Overview.

And for a more in-depth introduction check out the migration guide.

Alpha 1

And now comes alpha.1 with bug fixes, documentation updates, and several important feature unlocks.

Rendering

  • Camera frustum access for in-frame spatial queries.
  • Visibility lifecycle events: Visible, Framed, and Occluded.
  • Cameras are now part of the scene graph. Children of a camera will render correctly, enabling camera-attached objects by default.
  • Renderer-independent render targets, similar to useFBO, without needing to branch on the active renderer.

Scheduler

  • The scheduler no longer depends on R3F and can run standalone.
  • Scheduler context can now be shared outside the R3F tree, allowing external UIs or systems to participate in the frame loop while correctly waiting on the root set.

Documentation

  • New v10 features documentation.
  • Updated developer documentation.
  • Migration guide expanded, including details on taking over the renderer.

As always, feedback welcome. Consider all features experimental and may be changed, removed or expanded at any time. Who know,s you could be the reason 👀. Happy building!

What's Changed

Full Changelog: https://github.com/pmndrs/react-three-fiber/compare/v9.4.2...v10.0.0-alpha.1

2025-12-30 14:26:51
react-three-fiber

v9.5.0

After a bit of research and development, R3F is now compatible with React 19.2, including the Activity feature!

Why did this take some effort, you might wonder? When React bumped to version 19.2.x, they also bumped the internal reconciler up a version which was not backwards compatible with 19.1.x. This put us in an awkward position of either making a breaking change in the middle of R3F v9, bump to another major just because of an internal detail from React or get creative. We chose to get creative and R3F is compatible with all versions of React between 19.0 and 19.2. The downside is we had to bundle the reconciler with R3F, but react-dom already does this so for now it is the best solution available.

Forcing breaking changes on libraries is likely not what the React teams intended so we will be working with them to try to avoid this in the future.

Happy coding.

What's Changed

Full Changelog: https://github.com/pmndrs/react-three-fiber/compare/v9.4.2...v9.5.0

2025-11-29 17:53:04
react-three-fiber

v9.4.2

What's Changed

New Contributors

Full Changelog: https://github.com/pmndrs/react-three-fiber/compare/v9.4.1...v9.4.2