为什么我会收到此 useLayoutEffect 警告(不在测试中)

Why am I getting this useLayoutEffect warning (not in a test)

我有一个新创建的、几乎是空的 next/react/fiber 项目,带有光纤 Canvas。每次编译都会抛出以下警告。

Warning: useLayoutEffect does nothing on the server, because its effect cannot be encoded into the server renderer's output format. This will lead to a mismatch between the initial, non-hydrated UI and the intended UI. To avoid this, useLayoutEffect should only be used in components that render exclusively on the client. See https://reactjs.org/link/uselayouteffect-ssr for common fixes.
    at Canvas (C:\MyLocalFiles\Stratum\repos\cfgnext-updated\node_modules\@react-three\fiber\dist\react-three-fiber.cjs.dev.js:155:3)

这是说明问题的最小示例,其次是 package.json:

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

export default function Home() {
  return (
    <div>
        <Canvas>
        </Canvas>
    </div>
  )
}

package.json

{
  "name": "cfgnext-updated",
  "version": "0.1.0",
  "private": true,
  "scripts": {
    "dev": "next dev",
    "build": "next build",
    "start": "next start",
    "lint": "next lint"
  },
  "dependencies": {
    "@react-three/drei": "^9.0.1",
    "@react-three/fiber": "^8.0.6",
    "babel-plugin-styled-components": "^2.0.6",
    "next": "12.1.4",
    "react": "18.0.0",
    "react-dom": "18.0.0",
    "styled-components": "^5.3.5"
  },
  "devDependencies": {
    "eslint": "8.12.0",
    "eslint-config-next": "12.1.4"
  }
}

当我用其他纤维组件填充 Canvas 时,一切似乎都很完美。

谁能告诉我:

  1. 这实际上是一个合理的警告吗?如果没有
  2. 有没有办法消除它?

蒂亚, 比尔

通过 运行 useLayoutEffect 在服务器上您可能会发送不同的 html 内容,而不是第一次在客户端 运行 时应用程序将生成的内容时间,因此警告。 解决此问题的一种方法是不在服务器上呈现使用 useLayoutEffect 的组件。

您可以通过检查是否定义了 window 对象来做到这一点。当它被定义时,这意味着你的代码在客户端上是 运行,只有这样你才应该渲染你的 canvas 组件。

@juliomalves 上面的评论就是答案。谢谢你。我一直在寻找错误的地方。

这是更新后的代码,分为一个页面和一个动态加载的组件(包含一些新内容以提高可见性)。

import dynamic from 'next/dynamic'
import styled from "styled-components"

const Scene = dynamic(
  () => import('./scene'),
  { ssr: false }
)

export default function App() {
  return (
    <div>
      <ModelDiv>
          <Scene/>
      </ModelDiv>
    </div>
  )
}

const ModelDiv = styled.div`
  display: block;
  background-color: lightblue;
    width: 100%;
  height: 100vh;
`;

scene.js中对应的组件:

import { Canvas } from '@react-three/fiber'
import { OrbitControls } from '@react-three/drei'

export default function Scene() {
    return (
            <Canvas>
                <ambientLight intensity={1} />
                <directionalLight position={[0, 1, 5]} intensity={1} />
                <OrbitControls />
                <mesh>
                    <boxGeometry args={[1, 1, 1]} />
                    <meshStandardMaterial color="yellow" />
                </mesh>
            </Canvas>
    )
}