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

Next.js布局调用自定义Hook报错:is not a function的解决

问题解决与优化方案

一、先解决 default is not a function 错误

这个报错是因为自定义Hook的导出/导入方式不匹配:

  • 如果你的 useInitNavigation.ts 是用默认导出:
    // src/utils/useInitNavigation.ts
    export default function useInitNavigation() {
      // ...你的Hook逻辑
    }
    
    那导入时必须用默认导入:
    import useInitNavigation from '@/utils/useInitNavigation'
    
  • 如果是具名导出:
    // src/utils/useInitNavigation.ts
    export function useInitNavigation() {
      // ...你的Hook逻辑
    }
    
    导入时就得用解构:
    import { useInitNavigation } from '@/utils/useInitNavigation'
    

二、解决 layout.tsx 中 use client 与 metadata 冲突的问题

根布局 layout.tsx 里的 metadata 只能在服务器组件中定义,加 use client 会把组件转为客户端组件,必然冲突。正确做法是:
把导航栏拆成独立的客户端组件,让 layout.tsx 保持服务器组件身份(保留 metadata),只负责引入导航栏组件。

三、更优的导航高亮实现方案

直接用Next.js App Router自带的 usePathname API获取当前路径,无需额外写复杂Hook,步骤如下:

1. 创建独立的客户端导航栏组件

// components/Navbar.tsx
'use client'

import Link from 'next/link'
import { usePathname } from 'next/navigation'

export default function Navbar() {
  const currentPath = usePathname()

  // 生成高亮类名的辅助函数
  const getActiveClass = (href: string) => {
    return currentPath === href 
      ? 'text-blue-600 font-bold border-b-2 border-blue-600' 
      : 'text-gray-600 hover:text-gray-900'
  }

  return (
    <nav className="flex gap-6 p-4 border-b">
      <Link href="/" className={getActiveClass('/')}>首页</Link>
      <Link href="/about" className={getActiveClass('/about')}>关于我们</Link>
      <Link href="/blog" className={getActiveClass('/blog')}>博客</Link>
    </nav>
  )
}

2. 在根布局中引入导航栏组件

// app/layout.tsx
import type { Metadata } from 'next'
import { Inter } from 'next/font/google'
import Navbar from '@/components/Navbar'

const inter = Inter({ subsets: ['latin'] })

// 保留服务器组件中的metadata定义
export const metadata: Metadata = {
  title: '我的网站',
  description: 'Next.js导航栏高亮示例',
}

export default function RootLayout({
  children,
}: {
  children: React.ReactNode
}) {
  return (
    <html lang="zh-CN">
      <body className={inter.className}>
        {/* 引入客户端导航栏组件 */}
        <Navbar />
        <main className="container mx-auto mt-8">{children}</main>
      </body>
    </html>
  )
}

如果一定要复用你自己的 useInitNavigation Hook,只需要在 Navbar.tsx 中导入并调用即可,完全不会影响 layout.tsx 的服务器组件属性。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.22 23:33:10