首页 > 解决方案 > 如何在第一次运行时跳过运行 useEffect 是严格模式?

问题描述

我有一个自定义钩子,当我需要useEffect在第一次调用时跳过该函数的运行时使用它。这在非严格模式下就像一个魅力。

hooks/useEffectSkipFirst.js

import { useCallback, useEffect, useRef } from 'react';

export default (fn, deps) => {
  const isFirstRun = useRef(true);

  const execFunc = useCallback(fn, deps);

  useEffect(() => {
    if (isFirstRun.current) {
      isFirstRun.current = false;
      return;
    }
    execFunc();
  }, [execFunc])
};

用法:

import useEffectSkipFirst from 'hooks/useEffectSkipFirst';

useEffectSkipFirst(() => {
  // fetch new user by ID
}, [selectedUser.id])

显然,这个钩子在严格模式下的工作方式完全不同,它会在第一次调用时执行一个函数,因为useEffect钩子会被调用两次。它会被调用两次的原因是它的依赖是一个从useState(或 react-redux's useSelector)返回的变量,它在严格模式下被调用两次。因此,它会在第一次运行时进行 API 调用,而在用户更改之前不应调用。

我可以解决这个问题的唯一方法是听NODE_ENV变量,在开发的情况下,我会阻止函数的执行直到第 3 次调用,而在其他环境的情况下阻塞直到第 2 次调用。不幸的是,这对我来说听起来像是一个糟糕的解决方案。

有没有更好的方法来编写在两种模式下都可以使用的自定义钩子?请记住,编写一个不会引发任何eslint-plugin-react-hook警告的钩子很重要。

编辑:我的史诗般的脸。在非严格模式下一切都对我有用并且在严格模式下不起作用的原因是我的所有路线都是通过Private.js组件呈现的,该组件检查我是否已经有一个用户在商店(登录)或没有。如果我没有用户,它将进行 API 调用。因为我在渲染函数中进行检查(错误地在该检查中有副作用)并且在严格模式下调用了两次渲染,所以我实际上进行了 2 次 API 调用(错误)。这也意味着我的 Redux 存储被更新了两次,从而触发了我的 useEffect 两次,它将该变量作为依赖项。我一直在错误的地方寻找错误。我为浪费您的时间而道歉。

标签: javascriptreactjsreact-hooks

解决方案


推荐阅读