@react-three/drei stuff not working with next.js

Viewed 1354

Im not being able to use drei materials and other stuff, such as MeshWobbleMaterial or MeshDistortMaterial or even ContactShadows for example, I always get an error such as:

react-three-fiber.esm.js:1383 Uncaught TypeError: Cannot read property 'getState' of null at useFrame (react-three-fiber.esm.js:1383) at MeshDistortMaterial.js:72 (in the case of MeshDistortMaterial)

This null that it is referring is a 'useContext(context)' inside the useFrame module on react-three-fiber. I think this has something to do with the fact that I am also using next, version 10.1.3.

Here's the entire code:

import { useRef, useState, useMemo } from 'react'
import { Canvas } from 'react-three-fiber'
import { Box, MeshDistortMaterial } from '@react-three/drei'
import * as THREE from 'three'
import MyCamera from '../three/MyCamera'

//HERES WHERE THE MATERIAL IS USED
const MyBox = function (props) {
    const mesh = useRef()
  
    const [hovered, setHover] = useState(false)
    const [active, setActive] = useState(false)
  
    return (
      <Box
        args={[1, 1, 1]}
        {...props}
        ref={mesh}
        scale={active ? [6, 6, 6] : [5, 5, 5]}
        onClick={() => setActive(!active)}
        onPointerOver={() => setHover(true)}
        onPointerOut={() => setHover(false)}
        castShadow
      >
      
        <MeshDistortMaterial
          attach="material"
          distort={1} // Strength, 0 disables the effect (default=1)
          speed={10} // Speed (default=1)
        />

      </Box>
    )
}

//HERES JUST THE CANVAS STUFF
export default function Main() { 

  const dirLight = useMemo(()=>{
  
    const light = new THREE.DirectionalLight('white');
    light.castShadow=true;
    //Set up shadow properties for the light
    light.shadow.mapSize.width = 10240 // default
    light.shadow.mapSize.height = 10240 // default
    light.shadow.camera.near = 0.1 // default
    light.shadow.camera.far = 5000 // default
    light.shadow.camera.top = -100 // default
    light.shadow.camera.right = 100 // default
    light.shadow.camera.left = -100 // default
    light.shadow.camera.bottom = 100 // default
    return light
  
  },[])

  return (
    <div className="canvasContainer">
    <Canvas 
      linear = "true"
      frameloop="demand" 
      shadows = "true"
      shadowMap
    >
      
      <MyCamera position={[0, 0, 30]} infLimit={-1000} supLimit ={0} />
      
      <ambientLight intensity={0.2}/>

      <primitive object={dirLight} position={[30, 0, 30]} />
      <primitive object={dirLight.target} position={[0, 0, 0]}  />
      
      <mesh receiveShadow position={[0,0,-2]}>
        <planeBufferGeometry attach="geometry" args={[1000, 1000]} />
        <meshStandardMaterial attach="material" color="gray" />
      </mesh>
      
      <MyBox position={[8,0,0]}/>

    </Canvas>
    </div>
  )
}

Is there a way around it?

I am aware that working with next you need to install next-transpile-modules and create a next config file. I did that, here's my next.config.js

const withTM = require('next-transpile-modules')(['three', '@react-three/drei'])

module.exports = withTM()

Thank you very much for your help, its very difficult to troubleshoot this stuff with next.js.

2 Answers

Did you try to set your useMemo in a children of Canvas?

My guess is that your instantiate a DirectionalLight out of a scene context. And that could lead to this error.

To clarify, I was on the right path, but some of the packages was making this bug happen, after some time not being able to solve this issue, I unistalled and installed all depencies, and a lot of them were updated during this time, then it worked correctly.

Related