一个函数的多次执行

export default function MyQuestions() {
  const router = useRouter();

  const [auth,setauth] = useState(false);

  const checkAuth = async () => {
    const loggedInusername = await getusername();
    if (router.query.username === loggedInusername) return setauth(true);
    return;
  };
  checkAuth();

这是我执行 checkAuth 函数的 React 组件的一部分。我认为它应该只执行一次,但事实并非如此。它执行了 4 次,如果我删除返回,它甚至会执行 10 次以上,我不明白为什么。在 js 中,到达终点的函数应该自动停止。 为什么会发生这种情况?

在这段代码中,路由器是 Next.js

xiaoqi176 回答:一个函数的多次执行

我没有使用过 nextjs,但我想它会发生是因为它在路由器组件的每个渲染上执行。

如果想使用一次,就在组件挂载时的使用效果中调用即可。

useEffect(() => {
    checkAuth();
},[]) // This will run once,when the component mounts
,

不需要返回 setState 调用:

    const checkAuth = async () => {
        const loggedInUsername = await getUsername();
        if (router.query.username === loggedInUsername) setAuth(true);
    };

还因为您在调用 checkAuth() 函数后立即调用它。在 React 中设置状态会导致重新渲染。所以它被执行 4 到 10 次的原因是因为你的 MyQuestion 组件在你 setState() 时重新渲染,并且当它重新渲染时,再次点击 checkAuth() 函数并且循环重复。

如前所述,将功能放在具有空依赖数组的 useEffect() 中:

    useEffect(() => {
        const loggedInUsername = await getUsername();
        if (router.query.username === loggedInUsername) return setAuth(true);
    },[]) 
 
,

在什么情况下应该重新运行检查?这就是 useEffect 的用途。 useEffect 接受一个函数来运行所需的效果,以及一个依赖列表来指定何时应该运行效果 -

import { useRouter } from ...
import { useEffect,useState } from "react"

function MyQuestions() {
  const router = useRouter()
  const [auth,setAuth] = useState(false)
  
  useEffect(async () => {
    const loggedInUsername = await getUsername()
    if (router.query.username === loggedInUsername)
       setAuth(true)
  },[getUsername,router.query.username,setAuth])
  
  return <>...</>
}

任何效果内的自由变量必须列为效果的依赖项。不过有一个问题。每次呈现 setAuth 时,MyQuestions 都会是一个新函数。为了确保每次渲染的 setAuth 都相同,我们可以使用 useCallback -

import { useRouter } from ...
import { useEffect,useCallback,setAuth] = useState(false)

  const authenticate =
    useCallback(_ => setAuth(true),[])
  
  useEffect(async () => {
    const loggedInUsername = await getUsername()
    if (router.query.username === loggedInUsername)
       authenticate()
  },authenticate])
  
  return <>...</>
}

现在该效果只会在 getUsernamerouter.query.usernameauthenticate 更改时重新运行。考虑到 getUsernameauthenticate 是函数,不应该改变,我们可以预期效果只会在 router.query.username 改变时重新运行。

本文链接:https://www.f2er.com/5103.html

大家都在问