Error: its-fine: useFiber must be called within a <FiberProvider />!

Hi Friends!

I got a wired error when I tired to add my scene into a Next.js project. Everything works fine within the react application, but when I try to use the code in my Next.js application the n this error shows up. I dont understand whats wrong. It points to the react three fiber library within the node modules.

Here you can see a screnshot from the error:

This is the code:

import React, { useRef } from "react";
import { Canvas, extend, useThree, useFrame } from "react-three-fiber";
import {
  CubeTextureLoader,
  CubeCamera,
  WebGLCubeRenderTarget,
  RGBFormat,
  LinearMipmapLinearFilter,
} from "three";
import { OrbitControls } from "three/examples/jsm/controls/OrbitControls";

extend({ OrbitControls });

const CameraControls = () => {
  // Get a reference to the Three.js Camera, and the canvas html element.
  // We need these to setup the OrbitControls class.
  // https://threejs.org/docs/#examples/en/controls/OrbitControls

  const {
    camera,
    gl: { domElement },
  } = useThree();

  // Ref to the controls, so that we can update them on every frame using useFrame
  const controls = useRef();
  useFrame(() => controls.current.update());
  return (
    <orbitControls
      ref={controls}
      args={[camera, domElement]}
      autoRotate={true}
      autoRotateSpeed={0.05}
      enableZoom={true}
      enableDamping={true}
      dampingFactor={0.01}
    />
  );
};

// Loads the skybox texture and applies it to the scene.
function SkyBox() {
  const { scene } = useThree();
  const loader = new CubeTextureLoader();
  // The CubeTextureLoader load method takes an array of urls representing all 6 sides of the cube.
  const texture = loader.load([
    "./images/milkyway/ultra/px.webp",
    "./images/milkyway/ultra/nx.webp",
    "./images/milkyway/ultra/py.webp",
    "./images/milkyway/ultra/ny.webp",
    "./images/milkyway/ultra/pz.webp",
    "./images/milkyway/ultra/nz.webp",
  ]);

  // Set the scene background property to the resulting texture.
  scene.background = texture;
  return null;
}

// Geometry
function Sphere() {
  const { scene, gl } = useThree();
  // The cubeRenderTarget is used to generate a texture for the reflective sphere.
  // It must be updated on each frame in order to track camera movement and other changes.
  const cubeRenderTarget = new WebGLCubeRenderTarget(256, {
    format: RGBFormat,
    generateMipmaps: true,
    minFilter: LinearMipmapLinearFilter,
  });
  const cubeCamera = new CubeCamera(1, 1000, cubeRenderTarget);
  cubeCamera.position.set(0, 0, 0);
  scene.add(cubeCamera);

  // Update the cubeCamera with current renderer and scene.
  useFrame(() => cubeCamera.update(gl, scene));

  return (
    <mesh visible position={[0, 0, 0]} rotation={[0, 0, 0]} castShadow>
      <directionalLight intensity={5} />
      <sphereGeometry attach="geometry" args={[2, 32, 32]} />
      <meshBasicMaterial
        attach="material"
        envMap={cubeCamera.renderTarget.texture}
        color="white"
        roughness={1}
        metalness={1}
      />
    </mesh>
  );
}

// Lights
function MilkyWay() {
  return (
    <div className="canvas__wrapper">
      <Canvas className="canvas">
        <CameraControls />
        {/* <Sphere /> */}
        <SkyBox />
      </Canvas>
    </div>
  );
}

export default MilkyWay;

Can anyone help please?

Thanks for answers! :slight_smile:

I finally found the error…

The issue was that I installed a deprecated version from react-three-fibre. The deprecated version is called 'react-three-fiber' and the new version is called '@react-three/fiber'

Damn it, I love to enjoy the small things in live! :smiley:

also, most of the code you can cut

import { OrbitControls, Environment, CubeCamera } from '@react-three/drei'

<Canvas>
  <directionalLight intensity={5} />
  <CubeCamera resolution={256}>
    {texture => (
      <mesh castShadow>
        <meshBasicMaterial envMap={texture} roughness={0} metalness={1} />
        <sphereGeometry args={[2, 32, 32]} />
      </mesh>
    )}
  </CubeCamera>
  <OrbitControls autoRotate autoRotateSpeed={0.05} dampingFactor={0.01} />
  <Environment background files={["px", "nx", "py", "ny", "pz", "nz"].map(n => `/images/milkyway/ultra/${n}.webp`} />

there are lots of other useful helpers in drei: GitHub - pmndrs/drei: 🥉 useful helpers for react-three-fiber you should definitively check it out.

1 Like

@drcmda Thanks a lot for your advice!

I will definetly check out your code, because I also had the feeling that the code I am using is a bit mixed up. I was wondering why the sample code uses the standard three.js library instead of the functions provided in react-three-drei.

Actually I studied the drei library for a long time and I knew there should be a simpler way, so I highly apprechiate your code example :slight_smile:

One thing I recognized from the sample code is that we can also use the normal three.js library even within a react application, is this correct?

Actually that would be really helpful, because there are a lot of examples written in vanilla js with the standard three.js library, so it can be tricky sometimes to convert this code into another syntax provided from react three fibre/drei.

you probably just had an outdated example, drei is growing every single day, many of these features didn’t exist a year ago.

fiber is threejs, it’s just a different way to express it but it’s not wrapping it, or forcing you to use a specific version. you yourself need to install three, any version you want, and then ofc you can use it. many tasks are a mixture of declarative and imperative, you can’t, or shouldn’t try to avoid imperative, that’s what hooks like useEffect & useLayoutEffect are for, they allow you to cleanly separate and execute imperative side effects alongside the declarative view.

1 Like

@drcmda Thank you, this was a great explanation!