Library / SDK
pmndrs/drei avatar
pmndrs/drei

pmndrs/drei: helpers for react-three-fiber, and when to skip them

🥉 useful helpers for react-three-fiber

9,906 stars842 forksJavaScriptMIT

At a glance

What is it?
drei is a collection of ready-made components and hooks layered on top of react-three-fiber. It saves boilerplate for cameras, controls, loaders and materials, but it pulls in its own copy of three's addons and ships a separate native entry point.
Who is it for?
Adopt drei if you are already building with react-three-fiber and want cameras, controls, loaders and materials without writing them yourself; the install is one npm command and the imports are plain named exports. Skip it if you need a minimal bundle, if you avoid three's addon layer, or if you are not on react-three-fiber at all, because every component here assumes that renderer.
Can I use it commercially?
Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository received new commits within the last day.
What is it written in?
Mainly JavaScript, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on September 30, 2026, and from our analysis. They are not legal advice.

Editorial analysis

What drei is for, and who should reach for it

react-three-fiber lets you describe a three.js scene with React components, but it deliberately stays close to three's own API. That means a camera, an orbit control, a GLTF loader and a text mesh are all things you assemble yourself. drei fills that gap. The README describes it as "a growing collection of useful helpers and fully functional, ready-made abstractions for @react-three/fiber", and the old documentation index in the README lists the categories: cameras, controls, gizmos, abstractions, shaders and misc. A single import statement can pull a PerspectiveCamera, a PositionalAudio and anything else you need.

The audience is narrow and specific. If you are writing a three.js scene with plain JavaScript and no React, drei has nothing for you, because every export is a React component or hook. If you are using react-three-fiber and find yourself writing the same camera setup, the same scroll-driven animation or the same reflective floor material across projects, drei is the layer that removes that repetition. The package.json keywords are exactly react, three, threejs and react-three-fiber, which is a fair summary of the scope.

How drei sits on top of react-three-fiber

drei is not a renderer and does not replace react-three-fiber. It is a component library that renders into the react-three-fiber reconciler, so a drei component appears in the same React tree as your meshes and lights. The README's basic usage example is a single named import from the package, and the components are then used like any other JSX element.

Two structural details matter more than they first appear. First, the README states in an important note that the package uses the stand-alone three-stdlib instead of three/examples/jsm. That is a deliberate fork of three's addon code, and it means the addon classes drei uses are not the same module instances as the ones you get from three/examples/jsm. If your project already imports from three/examples/jsm, you have two copies of that layer in the bundle and two sets of class identities.

Second, drei ships more than one entry point. The default export is the web build. A separate native build is available at @react-three/drei/native, and the README is explicit that the native route does not export Html or Loader, while the default web export does. Choosing the wrong entry point is a compile-time error rather than a silent failure, but it is the first thing to get right in a React Native project.

The repository layout supports the rest of the picture: src/ holds the components, test/ holds tests including an e2e directory that the test script runs against a pinned three version, and sandboxes/ holds example scenes. The build is a rollup config plus a type generation step, and the package is marked sideEffects: false, which lets bundlers drop unused exports.

Installing drei and rendering a first scene

The README gives one install command. It assumes you already have react-three-fiber and three in the project, since drei is an add-on to them rather than a standalone renderer.

bash
npm install @react-three/drei

After that, the README's basic usage pattern is a named import from the package. The ellipsis in the README stands in for whatever components you actually need; the point is that everything comes from the same module path.

jsx
import { PerspectiveCamera, PositionalAudio } from '@react-three/drei'

For a React Native target, the README shows the same style of import but from the native subpath. Note the documented restriction: Html and Loader are not exported here.

jsx
import { PerspectiveCamera, PositionalAudio } from '@react-three/drei/native'

What you should see: a working named import with no additional configuration, and, for the native path, a module that resolves to the react-native field in package.json (native/index.cjs.js) rather than the web build. If the import fails to resolve, you are most likely on the wrong subpath for your target, or the peer packages are missing.

The three-stdlib decision and what it costs you

The stand-alone three-stdlib choice is the most consequential thing in the README, and it deserves more attention than the one-line note it gets. three's addon code lives under examples/jsm and is not part of the core module graph in the same way. By depending on a fork, drei can control which version of those addons it compiles against and avoid some of the churn in three's own examples directory.

The cost is duplication and identity. If your application imports OrbitControls from three/examples/jsm and drei imports its controls from three-stdlib, you can end up with two implementations of the same class in one bundle. That is a bundle-size question, and it is also a correctness question whenever code compares instances or relies on a shared registry. The README does not document a migration path for projects that already depend on three/examples/jsm, so this is something to check in your own dependency tree before adopting drei in an existing scene.

A second, smaller constraint: the test script in package.json runs the e2e suite against a pinned three version (the script passes 0.180 to the e2e shell script). That tells you the maintainers test against a specific three release rather than an open range, which is reassuring for reproducibility and less reassuring if you are pinned to an older three.

Where drei is the wrong tool

drei is the wrong choice when you are not using react-three-fiber. Nothing in the package is a plain three.js utility you can call from a non-React render loop; the exports are components and hooks that expect the react-three-fiber reconciler. If your scene is driven by an imperative animation loop, adding React just to get drei is a large architectural change for a small amount of saved code.

It is also the wrong choice if bundle size is the binding constraint and you only need one or two helpers. Because drei is a single package with a broad surface, you are depending on the whole thing and relying on tree shaking (the sideEffects: false flag is there to help) to drop what you do not use. Whether that shakes cleanly depends on your bundler, and the README does not make any claim about the resulting bundle size.

A third case: React Native projects that need Html or Loader. The README states plainly that the native route does not export them. If those two components are central to your design, the native entry point will not carry you, and you are back to solving that problem yourself.

drei versus writing the helpers yourself

The real alternative is not another library. It is writing the components yourself on top of react-three-fiber and three. That approach has one clear advantage: you control exactly which three addons you import, from which path, and at which version, so the three-stdlib duplication described above never arises. You also ship only the code you wrote.

The difference in approach is a difference in who maintains the abstraction. With drei, a camera component, a control wrapper and a material are maintained upstream, tested in the repository's test suite, and versioned with the package. With your own helpers, each of those is your code to keep in step with three's releases. drei's release history shows both tracks running at once: a stable line (v10.7.8, published 2026-08-05) and an alpha line (v11.0.0-alpha.7, published 2026-09-05), which is the normal shape for a library that tracks a fast-moving dependency.

For a one-off scene, hand-written helpers are usually the better trade. For a project that keeps several react-three-fiber scenes alive, the maintenance argument tilts toward drei, provided you accept the three-stdlib dependency.

Licence, maintenance and upgrade cost

drei is MIT licensed, and the LICENSE file sits at the repository root. MIT is permissive: you can use, modify and redistribute the code, including in closed-source products, provided the copyright notice and permission notice are preserved. That is a general description of the licence text, not legal advice; if your organisation has specific obligations around attribution or dependency review, read the LICENSE file and your own policy.

The maintenance picture is current. The last push to the default branch was on 2026-09-07, and the repository is not archived. Releases are frequent: v10.7.8 on 2026-08-05, then v11.0.0-alpha.6 on 2026-08-31 and v11.0.0-alpha.7 on 2026-09-05. The presence of an active alpha line alongside the stable line is the main upgrade consideration. The package.json version field is 0.0.0-semantic-release and the release config is committed, so versions are cut automatically from commits rather than by hand.

Upgrade cost is dominated by the three dependency rather than by drei's own API. Because drei wraps three's addons through three-stdlib and the e2e suite targets a pinned three version, a major three upgrade is the moment to re-read drei's release notes and check whether the components you use changed. The README does not document a rollback procedure, so pin your drei and three versions in lockfile terms before upgrading either.

Editorial conclusion

Adopt drei if you are already building with react-three-fiber and want cameras, controls, loaders and materials without writing them yourself; the install is one npm command and the imports are plain named exports. Skip it if you need a minimal bundle, if you avoid three's addon layer, or if you are not on react-three-fiber at all, because every component here assumes that renderer. Before committing, check which entry point you need (the default web export or @react-three/drei/native, which does not export Html or Loader) and confirm how three-stdlib interacts with any three/examples/jsm code you already import.

Frequently asked questions

What is React Drei?

It is @react-three/drei, a collection of helpers and ready-made abstractions for @react-three/fiber, described in the README as useful add-ons for react-three-fiber. It provides React components and hooks for things like cameras, controls, loaders, materials and text rather than a renderer of its own.

How do I install React Three Fiber and drei?

The README only gives the drei command, npm install @react-three/drei, and treats react-three-fiber as the package it builds on. Install react-three-fiber separately and then add drei, which imports from it rather than replacing it.

Can I use Three.js in React?

Yes, through react-three-fiber, which lets you describe a three.js scene with React components. drei is the add-on layer for that setup, exporting helpers such as PerspectiveCamera from @react-three/drei.

Can I use Three.js in React Native?

drei provides a native entry point at @react-three/drei/native, but the README states that this route does not export Html or Loader, while the default web export does. Plan around that gap if those two components are part of your design.

Official sources

  1. License: MIT
  2. pmndrs/drei on GitHub
  3. Project website
  4. README
  5. Releases
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/pmndrs-drei.svg)](https://hysenlabs.com/projects/pmndrs-drei)