You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Next.js引入P5.js制作的Logo组件即使在useEffect中仍报window未定义错误

问题原因

  1. useEffect用法错误:useEffect的返回值是清理函数,只会在组件卸载/依赖更新时执行,不会把你返回的JSX渲染到页面上,你写在useEffect里的组件代码根本不会正常渲染到视图中。
  2. 服务端渲染无window对象:react-p5-wrapper和p5.js本身依赖浏览器的window对象,Next.js默认在服务端渲染阶段就会执行导入和组件初始化,此时没有window对象,就会触发报错,和你写不写useEffect没有关系,导入阶段就已经执行了依赖的代码。

解决步骤

1. 单独封装p5 Logo组件

新建components/P5Logo.js文件,把p5相关的逻辑单独封装:

import { ReactP5Wrapper } from "react-p5-wrapper";
import sketch from './sketch';

const P5Logo = () => {
  return <ReactP5Wrapper sketch={sketch} mode='all_dir' />
}

export default P5Logo;

2. 动态导入组件并关闭服务端渲染

修改你的nav.js代码,用Next.js自带的next/dynamic导入组件,设置ssr: false让组件只在客户端加载:

import { useContext, useEffect } from 'react';
import dynamic from 'next/dynamic';
// 动态导入p5组件,关闭服务端渲染
const P5Logo = dynamic(() => import('./P5Logo'), { 
  ssr: false,
  // 可选:添加加载占位符
  loading: () => <div style={{width: '300px', height: '80px'}}></div>
});
// 补全你自己的MouseContext路径
import { MouseContext } from 'xxx';

const Nav = () => {
  const { cursorType, cursorChangeHandler } = useContext(MouseContext);

  useEffect(() => {
    if (typeof window !== 'undefined') {
      console.log('window已可用');
    }
  }, [])

  return (
    {/* 其他导航栏代码 */}
    <div id="logo_canvas">
      {/* 直接在return里渲染p5组件即可 */}
      <P5Logo />
    </div>
    {/* 其他导航栏代码 */}
  )
}

export default Nav;

注意事项

你的sketch代码里setup函数用到了document.getElementById("logo_canvas"),需要确保包裹P5Logo的父元素id确实为logo_canvas,否则会出现offsetWidth读取失败的报错。


内容的提问来源于stack exchange,提问作者Rom-888

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.30 06:39:01