简体   繁体   English

如何通过更改 React.js 中的动态值来停止递归 function

[英]How to stop a recursive function by the change of dynamic value in React.js

I am calling the verifyAuthentication function, and I want it to be called until no errors are thrown, but there are cases that I want it to stop dynamically, but I'm not achieving that.我正在调用verifyAuthentication function,我希望它被调用直到没有错误被抛出,但有些情况下我希望它动态停止,但我没有实现。

const callback = (object, error) => {
    if (error) {
      if (error === 'out of retries') {
        setRetry(0);
        return;
      }
    }
    if (object.data) {
      Cookies.set('token', object.data.token, { expires: 60000 });
      setIsAuthenticated(true);
      Router.push('/extrato').then(() => {
        setIsInLoginStep(true);
      });
    }
  };

  const verifyAuthentication = (
    sessionKey: string,
    _retries: number,
    cb: AuthContextInterface['callback'],
  ) => {
    console.log('Continuar Verificando', keepVerifying);
    if (keepVerifying) {
      api
        .post(`${API_ENDPOINT}/session/verify`, {
          sessionId: sessionKey,
        })
        .then((res) => {
          if (res.status === 200) {
            cb(res, null);
          } else if (_retries > 0) {
            const newRetry = _retries - 1;
            setTimeout(() => {
              verifyAuthentication(sessionKey, newRetry, cb);
            }, delay);
          } else {
            callback([], 'out of retries');
          }
        })
        .catch(() => {
          if (_retries > 0) {
            const newRetry = _retries - 1;
            setTimeout(() => {
              verifyAuthentication(sessionKey, newRetry, cb);
            }, delay);
          } else {
            callback([], 'out of retries');
          }
        });
    }
  };

I simply change the keepVerifying state for false, but on my logs, still see it as true, pretty sure this is because is is a recursive function.我只是将keepVerifying state 更改为 false,但在我的日志中,仍然将其视为 true,很确定这是因为它是一个递归的 function。

onClick={() => { setKeepVerifying(false) }}

Any tips on how to achiev that?关于如何实现这一目标的任何提示?

Whenever verifyAuthentication is called, its recursive calls will always be using the same closure that the initial verifyAuthentication has;每当verifyAuthentication时,它的递归调用将始终使用与初始verifyAuthentication相同的闭包 the keepVerifying (which was very likely declared with a const ) will not change in that closure. keepVerifying (很可能是用const声明的)在那个闭包中不会改变。

One option would be to use state to indicate if another call of verifyAuthentication should be run on next mount, eg:一种选择是使用 state 来指示是否应在下一次挂载时运行另一个verifyAuthentication调用,例如:

const [verifyAuthNextMount, setVerifyAuthNextMount] = useState(false);
useEffect(() => {
  if (verifyAuthNextMount) {
    setVerifyAuthNextMount(false);
    verifyAuthentication();
  }
}, [verifyAuthNextMount]
// Then, inside verifyAuthentication, instead of an immediate recursive call:
setVerifyAuthNextMount(true);

This will ensure that any given run of verifyAuthentication will have a reference to the most recent value of keepVerifying .这将确保任何给定的verifyAuthentication运行都将引用keepVerifying的最新值。

Another option would be to use a ref instead of state for keepVerifying , for which there's a stable reference across all renders.另一种选择是使用ref而不是 state 进行keepVerifying ,所有渲染都有一个稳定的参考。

const keepVerifyingRef = useRef(true);
// ...
// inside verifyAuthentication:
if (keepVerifyingRef.current) {
  api
    .post( // ...
}
// click handler:
onClick={() => { keepVerifyingRef.current = false; }}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM