NextJS 14中使用Suspense与Loader报window未定义错误的解决咨询
解决NextJS 14中Suspense + Loader出现
window is not defined的思路 1. 给Loader组件加上客户端标识
这个错误大概率是因为你的Loader组件在服务端渲染时访问了浏览器专属的window对象(比如用了动画库、DOM操作或者依赖window的第三方组件)。NextJS 14的App Router里,只需在Loader组件的文件顶部添加'use client';指令,把它标记为客户端组件——这类组件只会在浏览器环境执行,自然能正常访问window:
// Loader.jsx 'use client'; export default function Loader() { return <div>加载中...</div>; }
2. 检查数据获取代码是否违规
如果你的GraphQL数据获取逻辑里也用到了window(比如某些客户端GraphQL库在初始化时依赖window),分两种情况处理:
- 若用的是App Router的Server Component异步数据获取:确保数据获取代码只在服务端执行(比如直接用
fetch调用GraphQL接口,或者用支持服务端的GraphQL客户端),不要在Server Component里写依赖window的代码。 - 若必须在客户端获取数据:把数据获取逻辑移到加了
'use client';的组件里,搭配useEffect、useSWR或react-query这类客户端数据获取工具,避免在服务端渲染阶段执行。
3. 给依赖window的代码加安全判断
如果Loader里有部分代码必须访问window,可通过typeof window !== 'undefined'做环境判断,或者把这部分逻辑放到useEffect里(useEffect只在客户端触发):
'use client'; import { useEffect, useState } from 'react'; export default function Loader() { const [width, setWidth] = useState(0); useEffect(() => { // 仅在客户端执行的代码 setWidth(window.innerWidth); }, []); return ( <div style={{ width: `${width / 2}px` }}> 加载中... </div> ); }
4. 调整Suspense的使用姿势
在App Router中,正确的Suspense用法是包裹异步Server Component,比如你的数据展示组件是async的:
// 页面组件(Server Component,无需加'use client') import { Suspense } from 'react'; import Loader from './Loader'; // 已加'use client'的Loader import DataDisplay from './DataDisplay'; // 异步Server Component,负责获取GraphQL数据 export default async function Page() { return ( <Suspense fallback={<Loader />}> <DataDisplay /> </Suspense> ); } // DataDisplay.jsx(async Server Component) export default async function DataDisplay() { // 这里写服务端安全的GraphQL数据获取逻辑,比如用fetch调用API const data = await fetch('/api/graphql', { method: 'POST', body: JSON.stringify({ query: '你的GraphQL查询' }) }).then(res => res.json()); return <div>{JSON.stringify(data)}</div>; }
内容的提问来源于stack exchange,提问作者user23658086
相关产品推荐
相关产品推荐

