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

Next.js中useEffect内setState未触发问题排查

为什么调用setCurrent后current仍显示初始值?

问题场景

在Next.js客户端组件中,useEffect里的所有console.log都能输出正确的路由值,但调用setCurrent(router.asPath)后,紧接着打印current却还是初始值TEST。

代码示例

import { useContext, useEffect, useState } from "react";
import Link from "next/link";
import { UserContext } from "../context";
import { useRouter } from "next/router";

const Nav = () => {
  const [current, setCurrent] = useState("TEST");
  const [state, setState] = useContext(UserContext);
  const router = useRouter();

  // 先判断是否运行在客户端,是则将状态设置为路径名,路径变化时更新
  useEffect(() => {
    console.log("router.asPath ", router.asPath);
    console.log("window.location.pathname is ", window.location.pathname);
    console.log(typeof window !== "undefined");
    if (typeof window !== "undefined") {
      console.log("this ran before");
      setCurrent(router.asPath);
      console.log("this ran after");
      console.log("current is ", current);
    }
  }, [typeof window !== "undefined" && window.location.pathname]);
  //...
}

控制台输出

router.asPath  /register
window.location.pathname is  /register
true
this ran before
this ran after
current is TEST

原因分析

  1. React状态更新是异步的
    setCurrent是异步操作,调用后不会立刻修改current的值。你在调用setCurrent后马上打印的current,是当前函数闭包里捕获的旧状态值,不是更新后的新值。

  2. useEffect依赖数组存在逻辑问题
    你写的依赖项[typeof window !== "undefined" && window.location.pathname]有问题:

  • 这个表达式会返回布尔值或路径字符串,依赖关系不稳定,可能导致useEffect触发异常
  • 在Next.js中,直接依赖router.asPath监听路由变化更可靠,useRouter本身就是客户端钩子,无需手动判断window

解决方法

调整useEffect的依赖,并通过监听current的变化验证状态更新:

import { useContext, useEffect, useState } from "react";
import Link from "next/link";
import { UserContext } from "../context";
import { useRouter } from "next/router";

const Nav = () => {
  const [current, setCurrent] = useState("TEST");
  const [state, setState] = useContext(UserContext);
  const router = useRouter();

  useEffect(() => {
    console.log("router.asPath ", router.asPath);
    // 直接更新状态
    setCurrent(router.asPath);
  }, [router.asPath]); // 依赖router.asPath,路由变化时自动触发

  // 专门监听current的变化,打印更新后的值
  useEffect(() => {
    console.log("current已更新为: ", current);
  }, [current]);

  //...
}

修改后,路由变化时current会被正确更新,第二个useEffect会在current变化时打印出新值。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.27 04:12:57