Next.js引入P5.js制作的Logo组件即使在useEffect中仍报window未定义错误
问题原因
- useEffect用法错误:useEffect的返回值是清理函数,只会在组件卸载/依赖更新时执行,不会把你返回的JSX渲染到页面上,你写在useEffect里的组件代码根本不会正常渲染到视图中。
- 服务端渲染无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
相关产品推荐
相关产品推荐

