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

如何修复Next.js项目中React Hook条件式调用错误?

解决React Hooks条件式调用报错问题

报错信息

./src/lib/session.js
6:29  Error: React Hook "React.useState" is called conditionally. React Hooks must be called in the exact same order in every component render.  react-hooks/rules-of-hooks
10:3  Error: React Hook "React.useEffect" is called conditionally. React Hooks must be called in the exact same order in every component render. Did you accidentally call a React Hook after an early return?  react-hooks/rules-of-hooks

问题根源

你的useSessionStorage钩子在开头就做了typeof window == 'undefined'的判断并直接return,导致后面的useState和useEffect只有在客户端环境才会被调用,违反了React Hooks的核心规则:Hooks必须在组件的每次渲染中按完全相同的顺序被调用,不能放在条件语句、循环或者可能提前return的代码后面。

另外getFromStorage和setToStorage函数里存在拼写错误:window.localstorage应该是window.localStorage(注意S大写)。

修复方案

把条件判断移到Hooks内部,确保Hooks每次都能被调用:

  1. 先调用useState,在初始化值的时候处理服务端/客户端差异;
  2. 在useEffect的回调里先判断window是否存在,再执行localStorage操作;
  3. 把服务端环境的return逻辑移到Hooks调用之后,避免影响Hooks调用顺序。

修复后的完整代码

import React from 'react'

export const useSessionStorage = (storageKey, fallbackState) => {
  // 先调用useState,初始化时处理服务端/客户端差异
  const [value, setValue] = React.useState(() => {
    if (typeof window === 'undefined') {
      return fallbackState
    }
    return JSON.parse(window.localStorage.getItem(storageKey)) ?? fallbackState
  })

  React.useEffect(() => {
    // 先判断是否在客户端环境,再执行localStorage操作
    if (typeof window !== 'undefined') {
      window.localStorage.setItem(storageKey, JSON.stringify(value))
    }
  }, [value, storageKey])

  // 服务端环境返回fallback和null,客户端返回正常的value和setValue
  if (typeof window === 'undefined') {
    return [fallbackState, null]
  }
  return [value, setValue]
}

export const getFromStorage = (key) => {
  if (typeof window !== 'undefined') {
    return window.localStorage.getItem(key)
  }
  return null
}

export const setToStorage = (key, value) => {
  if (typeof window !== 'undefined') {
    return window.localStorage.setItem(key, value)
  }
  return null
}

补充说明

  • React Hooks的调用顺序是React跟踪状态的关键,任何可能改变调用顺序的操作(比如条件return、循环里调用)都会触发报错;
  • Next.js是服务端渲染框架,服务端没有window对象,所以所有涉及window的操作都需要做存在性判断,但要注意不能影响Hooks的调用顺序。

内容的提问来源于stack exchange,提问作者annn

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.20 16:42:14