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

NextJS项目修改导航栏后出现useState Hook调用错误求助

解决NextJS中「Error: React Hook "useState" is called in function」错误

错误原因

你定义的组件用了小写开头的函数名header,React会把它当成普通JavaScript函数,而非React组件。而React Hook(比如useState、useEffect)只能在React组件或自定义Hook里调用,这就是报错的直接原因。

修复步骤

  1. 把组件函数名改成大写开头的Header(React规范要求组件名必须大写)
  2. 同步修改导出语句,确保导出的是大写的组件名

修复后的完整代码

import NextLink from "next/link";
import { useEffect, useState } from "react";
import { useRouter } from "next/router";
import cx from "classnames";
import IconArrowDropDown from "./icons/arrow-drop-down";

const MENU = {
  "/": "Home",
  "/works": "Works",
  "/resume": "Resume",
  "/post": "Blog",
  "/contact": "Contact",
};

const Header = () => {
  const [isNavOpen, setIsNavOpen] = useState(false);
  const router = useRouter();
  // 只调用一次useRouter,避免重复获取实例
  const { pathname } = router;
  
  const clearSlash = pathname.split("/")[1];
  const pathName = clearSlash ? `/${clearSlash}` : "/";

  useEffect(() => {
    const handleRouteChangeStart = () => {
      setIsNavOpen(false);
    };

    router.events.on("routeChangeStart", handleRouteChangeStart);
    return () => {
      router.events.off("routeChangeStart", handleRouteChangeStart);
    };
  }, [router]); // 添加router依赖,避免闭包问题

  return (
    <header>
      <div className="max-w-screen-sm mx-auto flex flex-row justify-between py-6 px-6">
        <NextLink href="/">
          <a className="text-gray-900 text-xl">
            <span className="ml-3 font-bold text-xl">onurhan.dev</span>
          </a>
        </NextLink>
        <nav
          className={cx(
            isNavOpen ? "flex" : "hidden",
            "flex-col gap-x-6 sm:!flex sm:flex-row"
          )}
        >
          {Object.keys(MENU).map((path) => {
            const isActive = path === pathName;
            return (
              <span key={path}>
                <NextLink href={path}>
                  <a className={cx(isActive ? "text-zinc-900" : "text-gray-600")}>
                    {MENU[path]}
                  </a>
                </NextLink>
              </span>
            );
          })}
        </nav>

        {!isNavOpen && (
          <button
            type="button"
            className="flex bg-zinc-100 text-gray-700 px-3 py-1 rounded-full select-none items-center sm:hidden"
            onClick={() => {
              setIsNavOpen(true);
            }}
          >
            <span>{MENU[pathName]}</span>
            <IconArrowDropDown className="opacity-50" />
          </button>
        )}
      </div>
    </header>
  );
};

export default Header;

额外优化说明

  • 移除了重复的useRouter()调用,只在组件顶部获取一次路由实例,减少不必要的性能开销
  • 给useEffect添加router依赖项,解决闭包导致的路由事件监听异常问题

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.21 08:18:40