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

Next.js中如何通过Link组件跨路由传递方法类型props?

问题根源

你用路由query传函数的方案本身就不成立:

  • Next.js的路由query参数仅支持可序列化的基础类型(字符串、数字、布尔值,以及上述类型的只读数组),函数属于不可序列化的引用类型,直接传入会触发你遇到的类型错误。
  • getServerSideProps运行在服务端环境,根本无法获取客户端组件中定义的函数引用,哪怕绕过类型校验也拿不到正确的函数执行逻辑。
推荐实现方案

你要实现的核心需求是登录后全局同步导航栏的登录状态,根本不需要跨页面传递函数,登录状态属于全局通用状态,用React Context托管是最简单、符合框架设计规范的做法。

步骤1:创建全局鉴权上下文

新建鉴权上下文文件,统一管理登录状态、登录/登出方法,所有组件都可以直接调用,不需要跨页面传参:

// contexts/AuthContext.js
import { createContext, useContext, useState, useEffect } from 'react'

const AuthContext = createContext({})

export const AuthProvider = ({ children }) => {
  const [loggedIn, setLoggedIn] = useState(false)

  useEffect(() => {
    // 初始化时读取本地存储的token,判断初始登录状态
    setLoggedIn(!!localStorage.getItem("token"))
  }, [])

  const handleLogin = (token) => {
    localStorage.setItem("token", token)
    setLoggedIn(true)
  }

  const handleLogout = () => {
    localStorage.removeItem("token")
    setLoggedIn(false)
  }

  return (
    <AuthContext.Provider value={{ loggedIn, handleLogin, handleLogout }}>
      {children}
    </AuthContext.Provider>
  )
}

// 自定义hook方便组件调用
export const useAuth = () => useContext(AuthContext)

步骤2:全局注入上下文

在Next.js的_app.js文件中给整个应用包裹鉴权上下文Provider:

// pages/_app.js
import { AuthProvider } from '../contexts/AuthContext'

function MyApp({ Component, pageProps }) {
  return (
    <AuthProvider>
      <Component {...pageProps} />
    </AuthProvider>
  )
}

export default MyApp

步骤3:改造Navbar组件

直接从全局上下文拿登录状态和登出方法,不需要再接收token参数、也不需要在跳转时传函数:

const Navbar = () => {
  const { loggedIn, handleLogout } = useAuth()
  return (
    <>
      {loggedIn ? (
        <a onClick={handleLogout} className="nav-link" style={{cursor: 'pointer'}}>
          log out <FontAwesomeIcon icon={faUser}/>
        </a>
      ) : (
        <Link href="/login">
          <a className="nav-link">Sign in <FontAwesomeIcon icon={faUser}/></a>
        </Link>
      )}
    </>
  )
}

步骤4:改造Login页面

删除原来getServerSideProps中传递函数的逻辑,登录成功后直接调用全局上下文的handleLogin方法即可,Navbar会自动同步状态更新:

import { useRouter } from 'next/router'

const Login = () => {
  const router = useRouter()
  const { handleLogin } = useAuth()
  const [errors, setErrors] = useState([])
  const [user, setUser] = useState({email: '', password: ''})

  // 保留你原有的validate校验逻辑
  const validate=async()=>{
    // 原有逻辑不变
  }

  const handleSubmit=async(e:React.SyntheticEvent)=>{
    e.preventDefault();
    const validateResult=await validate()
    if(validateResult==true){
      try{
        const response=await axios.post(`https://reqres.in/api/login`,user)
        const token=response.data.token;
        // 调用全局登录方法,Navbar会自动更新状态
        handleLogin(token)
        // 登录成功后返回上一页或者首页
        router.back()
      }
      catch(er){
        setErrors(["The username or password is incorrect"])
        localStorage.setItem("token","")
      }
    }
  }

  const handleChange=(e:React.ChangeEvent<HTMLInputElement>)=>{
    setUser({...user,[e.currentTarget.id]:e.currentTarget.value})
  }

  // 原有页面渲染逻辑不变
  return (
    // 原有JSX代码不变
  )
}

// 删掉原来的getServerSideProps逻辑,不需要传函数
export default Login;
原有代码其他需要修正的问题
  • useState用法错误:你写的var [loggedIn,setLoggedIn]=false不符合React hooks规则,必须通过useState声明状态。
  • Link嵌套a标签的写法错误:a标签不要加href=""属性,会覆盖Next.js的客户端路由行为,触发整页刷新。
  • 登录逻辑写反:登录成功回调不应该执行localStorage.removeItem("token"),这个逻辑应该放在登出方法里。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.28 13:21:26