使用 NextJS 路由器时的 useEffect 依赖项
Posted
技术标签:
【中文标题】使用 NextJS 路由器时的 useEffect 依赖项【英文标题】:useEffect dependencies when using NextJS router 【发布时间】:2021-11-11 03:47:32 【问题描述】:我有一个 NextJS 项目,使用 NextJS 路由器根据某个状态变量将用户路由到页面。
我查找了如何使用 NextJS router documents 执行我想要的操作,其中包含以下示例:
const useUser = () => ( user: null, loading: false )
export default function Page()
const user, loading = useUser()
const router = useRouter()
useEffect(() =>
if (!(user || loading))
router.push('/login')
, [user, loading])
return <p>Redirecting...</p>
当我将该示例粘贴到我的代码中时,ESLint 对我没有将路由器作为依赖项包含在内感到不高兴 - 显示以下消息:
React Hook useEffect has a missing dependency: 'router'. Either include it or remove the dependency array.eslintreact-hooks/exhaustive-deps
消息是有道理的——我们在效果中使用了 useRouter 挂钩,但没有将它添加到效果的依赖数组中。
但是,将它添加到依赖数组自然会导致无限的重新渲染循环(因为我使用的是动态路由,因此由于路由器正在更改,因此会一遍又一遍地调用相同的效果)。
我应该忽略 ESLint 的警告,还是应该一起做一些不同的事情?
编辑:值得注意的是我使用的是NextJS ESlint config
【问题讨论】:
该问题的讨论是here。虽然我没有找到具体的解决方案。 【参考方案1】:目前,这是一个错误。
useRouter
方法似乎改变了useRouter
本身。因此,每次您调用其中一种方法时,useRouter
都会发生变化并导致此循环。
另一个问题是 Next.js 没有记住useRouter
,所以即使值相同,它也会改变。
目前,我发现的最接近的解决方法来自对此未决问题 https://github.com/vercel/next.js/issues/18127#issuecomment-950907739 的评论。
它的作用是将useRouter
“转换”为useRef
并导出push
方法。所以每次你使用这个方法时,如果值没有改变,这个引用就不会改变。
解决方法:
我很快想到了这个,这似乎奏效了:
import useRouter from 'next/router'
import type NextRouter from 'next/router'
import useRef, useState from 'react'
export default function usePush(): NextRouter['push']
const router = useRouter()
const routerRef = useRef(router)
routerRef.current = router
const [ push ] = useState<Pick<NextRouter, 'push'>>(
push: path => routerRef.current.push(path),
)
return push
它返回一个语义记忆的推送函数,因此可以安全地与 useEffect 一起使用,例如
const push = usePush()
useEffect(() =>
checkLoggedIn().then(loggedIn =>
if (!loggedIn)
push('/login')
)
, [push])
【讨论】:
【参考方案2】:@mledezma 提出的解决方法效果很好,如果你还不能理解 TS,这是一个 JS 重构:
import useRef, useState from "react";
import useRouter from "next/router";
export const usePush = () =>
const router = useRouter();
const routerRef = useRef(router);
routerRef.current = router;
const [routerPush] = useState(() =>
const push = (path) =>
routerRef.current.push(path);
;
return push;
);
return routerPush;
;
【讨论】:
以上是关于使用 NextJS 路由器时的 useEffect 依赖项的主要内容,如果未能解决你的问题,请参考以下文章
NextJS 中的 LocalStorage , useEffect 问题
React - nextjs 在 useEffect 中调用自定义钩子
React/NextJS 使用 UseEffect 错误:渲染的钩子比上一次渲染期间更多
NextJs:在 React useEffect Hook 内使用变量调用 setInterval