Next.js报错ReferenceError: window is not defined 解决方案咨询
报错原因
Next.js 默认会在 Node.js 服务端完成组件/页面的预渲染流程,服务端运行环境不存在浏览器专属的window、document等全局API。
你当前把访问window.location的逻辑写在了模块顶层,代码在服务端编译执行阶段就会触发这行逻辑,直接抛出ReferenceError: window is not defined。
你之前注释掉的存在性判断思路是对的,但在if块内用const声明的变量是块级作用域,块外的组件代码根本访问不到code变量,就算取消注释也会触发新的未定义错误。
相关报错截图:
修复方案
根据你的使用场景选一种即可:
- 方案1:把
window相关逻辑移到仅客户端执行的生命周期里(通用兼容写法,全Next.js版本可用)useEffect内的代码只会在客户端hydration完成后执行,不会在服务端运行,从根源避免访问不到window的问题,参考修改后的代码:import React, { createContext, useState, useContext, useEffect } from "react"; import useAuth from '../hooks/useAuth'; import axios from "axios"; export const SpotifyContext = createContext() function SpotifyProvider({ children }){ const [code, setCode] = useState(null) useEffect(() => { // 此处代码仅客户端运行,可安全访问window const urlCode = new URLSearchParams(window.location.search).get("code") setCode(urlCode) }, []) const { accessToken, connecting, SignOut, error, setError, tokenExpired } = useAuth(code) const headers = { Authorization: `Bearer ${accessToken}`, 'Content-Type': 'application/json', } // 原有组件剩余逻辑... } - 方案2:用Next.js官方路由API获取查询参数(推荐,框架原生兼容SSR)
不需要自己手动访问window.location,框架封装的钩子已经做了服务端兼容:- 如果你用Next.js 13+ App Router,首先在文件顶部加
'use client'指令(Context Provider必须是客户端组件),然后用useSearchParams取值:'use client' import { useSearchParams } from 'next/navigation' function SpotifyProvider({ children }){ const searchParams = useSearchParams() const code = searchParams.get('code') // 剩余原有逻辑... } - 如果你用Pages Router,直接用
useRouter取query参数即可:import { useRouter } from 'next/router' function SpotifyProvider({ children }){ const router = useRouter() const code = router.query.code // 剩余原有逻辑... }
- 如果你用Next.js 13+ App Router,首先在文件顶部加
- 方案3:修正顶层判断的作用域问题(快速修复,不推荐用于依赖参数渲染内容的场景)
把变量声明提到判断外面,避免块级作用域导致的访问问题:const code = typeof window !== "undefined" ? new URLSearchParams(window.location.search).get("code") : null注意:这种写法下服务端拿到的
code永远是null,如果组件首屏渲染内容依赖code的值,大概率会出现服务端和客户端渲染内容不一致的hydration报错,非必要不选这个方案。
内容的提问来源于stack exchange,提问作者cccccc03
相关产品推荐
相关产品推荐

