NextJS项目修改导航栏后出现useState Hook调用错误求助
解决NextJS中「Error: React Hook "useState" is called in function」错误
错误原因
你定义的组件用了小写开头的函数名header,React会把它当成普通JavaScript函数,而非React组件。而React Hook(比如useState、useEffect)只能在React组件或自定义Hook里调用,这就是报错的直接原因。
修复步骤
- 把组件函数名改成大写开头的
Header(React规范要求组件名必须大写) - 同步修改导出语句,确保导出的是大写的组件名
修复后的完整代码
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
相关产品推荐
相关产品推荐

