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

使用next/router重定向时触发Invalid hook call错误的解决咨询

修复Next.js中useRouter钩子调用无效的错误

错误原因

你遇到的Invalid hook call错误,是因为**useRouter是React Hook,必须严格遵循Hook规则:只能在函数组件的顶层作用域,或者自定义Hook的顶层调用**。你现在把它放在了普通异步函数DispatchApi里,违反了这个规则,所以触发报错。

解决方案

下面提供两种可行的修复方式,根据你的使用场景选择:

方案一:从调用组件传递router实例

既然普通函数不能用Hook,就从调用DispatchApi的React组件中获取router实例,再传递给函数:

修改DispatchApi函数,新增router参数:

import { Axios } from '../axios'
import { Languages } from '../business/language'
import { NextRouter } from 'next/router'

export async function DispatchApi({
  address,
  sendedData,
  lan = Languages.fa,
  method,
  router,
}: {
  address: string
  sendedData: string
  lan: Languages
  method: 'POST' | 'GET'
  router: NextRouter
}) {
  let data = JSON.parse(sendedData)
  
  // 添加请求拦截器
  const interceptorId = Axios.interceptors.request.use((config) => {
    router.push('login')
    return config
  })

  try {
    const response = await Axios({
      url: address,
      data,
      method,
      headers: {
        accept: '*/*',
        'Accept-Language': lan,
        'Content-Type': 'application/json',
      },
    })
    return response.data
  } finally {
    // 必须移除拦截器,避免重复添加导致内存泄漏或多次跳转
    Axios.interceptors.request.eject(interceptorId)
  }
}

在调用该函数的组件中,用useRouter获取实例并传递:

import { useRouter } from 'next/router'
import { DispatchApi } from './path/to/DispatchApi'
import { Languages } from '../business/language'

export default function MyComponent() {
  const router = useRouter()

  const handleApiRequest = async () => {
    const result = await DispatchApi({
      address: '/api/user',
      sendedData: JSON.stringify({ id: 1 }),
      lan: Languages.fa,
      method: 'POST',
      router, // 传递router实例
    })
    // 处理接口返回结果
  }

  return <button onClick={handleApiRequest}>发起请求</button>
}

方案二:直接导入Next.js的router实例(仅客户端场景)

Next.js提供了无需Hook的全局router实例,适合在纯客户端环境的普通函数中使用:

修改DispatchApi函数:

import { Axios } from '../axios'
import { Languages } from '../business/language'
import router from 'next/router' // 直接导入全局router实例

export async function DispatchApi({
  address,
  sendedData,
  lan = Languages.fa,
  method,
}: {
  address: string
  sendedData: string
  lan: Languages
  method: 'POST' | 'GET'
}) {
  let data = JSON.parse(sendedData)
  
  const interceptorId = Axios.interceptors.request.use((config) => {
    router.push('login')
    return config
  })

  try {
    const response = await Axios({
      url: address,
      data,
      method,
      headers: {
        accept: '*/*',
        'Accept-Language': lan,
        'Content-Type': 'application/json',
      },
    })
    return response.data
  } finally {
    Axios.interceptors.request.eject(interceptorId)
  }
}

⚠️ 注意:这个方法不能在服务器端渲染(SSR)场景使用,比如getServerSideProps、getStaticProps中,因为全局router实例仅在浏览器环境存在。

额外注意事项

  • 无论哪种方案,都要在请求完成后用eject移除Axios拦截器,否则每次调用函数都会新增拦截器,导致重复跳转和内存泄漏。
  • 如果你的接口调用涉及SSR场景,建议优先用方案一,或者在服务器端直接通过res.redirect处理重定向逻辑。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.10 17:25:19