使用React 16.8.6(在之前的版本16.8.3上很好),当我试图阻止fetch请求上的无限循环时,我得到了这个错误:

./src/components/BusinessesList.js
Line 51:  React Hook useEffect has a missing dependency: 'fetchBusinesses'.
Either include it or remove the dependency array  react-hooks/exhaustive-deps

我一直无法找到一个解决办法来停止这个无限循环。我想远离使用useReducer()。我确实找到了关于'筋疲力尽-deps' lint规则#14920的讨论[ESLint]反馈,其中一个可能的解决方案是,如果你认为你知道你在做什么,你可以总是// ESLint - disabled -next-line react-hooks/详尽-deps。我对我正在做的事情没有信心,所以我还没有尝试实现它。

我有这个当前的设置,React钩子useEffect连续运行永远/无限循环,唯一的评论是关于useCallback(),我不熟悉。

我目前如何使用useEffect()(我只想在开始时运行一次,类似componentDidMount()):

useEffect(() => {
    fetchBusinesses();
  }, []);
const fetchBusinesses = () => {
    return fetch("theURL", {method: "GET"}
    )
      .then(res => normalizeResponseErrors(res))
      .then(res => {
        return res.json();
      })
      .then(rcvdBusinesses => {
        // some stuff
      })
      .catch(err => {
        // some error handling
      });
  };

当前回答

使用UseEffect fetchBusinesses调用UseEffect()中的function declare,在调用函数名后声明一个const变量,

useEffect(()=>{
const fetchBusinesses=()=>{
   console.log(useeffect fetchbussinesses functions)
}
 fetchBusinesses();
},[declare the variable used in useeffect hooks ])

其他回答

你可以这样尝试:

const fetchBusinesses = () => {
    return fetch("theURL", {method: "GET"})
        .then(res => normalizeResponseErrors(res))
        .then(res => {
            return res.json();
        })
        .then(rcvdBusinesses => {
            // Some stuff
        })
        .catch(err => {
            // Some error handling
        });
  };

and

useEffect(() => {
    fetchBusinesses();
});

这对你有用。

但我的建议是试试这种方法,它也适用于你。 这比以前的方法好。我是这样用的:

useEffect(() => {
    const fetchBusinesses = () => {
        return fetch("theURL", {method: "GET"})
            .then(res => normalizeResponseErrors(res))
            .then(res => {
                return res.json();
            })
            .then(rcvdBusinesses => {
                // Some stuff
            })
            .catch(err => {
                // Some error handling
            });
    };

    fetchBusinesses();
}, []);

如果您根据特定的id获取数据,则在回调中添加useEffect [id]。然后它就不能显示警告 React钩子useEffect有一个缺失的依赖:'any thing'。要么包含它,要么删除依赖数组

这些警告对于查找不一致更新的组件非常有帮助:从依赖项列表中省略函数是否安全?

然而,如果你想在你的项目中删除警告,你可以添加到你的ESLint配置:

  {
  "plugins": ["react-hooks"],
  "rules": {
    "react-hooks/exhaustive-deps": 0
    }
  }

你正在使用useEffect,当你这样做的时候,你经常会想要使用一些变量作为你的组件中的道具或状态。

eslint中有一个规则,它希望你引用useEffect依赖数组中任何不同的道具或状态块。这是控制何时执行useEffect的数组。该规则希望看到它列在数组中,数组决定何时重新运行useEffect函数。

因此,您需要添加[fetchBusinesses],这样警告就会消失。

为什么这个规则要我们把它写在这里?

在某些情况下,使用useEffect而没有正确列出数组内的所有状态和道具,可能会导致奇怪且难以调试的问题。

因此,这条规则有助于避免使用useEffect可能出现的那些难以理解的问题。

现在,任意添加到该数组也会导致错误。所以无论哪种方式,你都遇到了必须解决的bug。根据你的评论,似乎为你解决了这个问题,但我想进一步调查,看看你是否有机会在你的网络选项卡在Chrome中添加fetchBusinesses函数到你的useEffect数组后得到第二个GET请求。

如果你正在创建一个新的应用程序或有足够的灵活性,有非常好的状态管理库的选择。看看《后坐力》。

为了完整起见:

1. (停止工作)使用函数作为useEffect回调

useEffect(fetchBusinesses, [])

2. 在useEffect()中声明函数

useEffect(() => {
  function fetchBusinesses() {
    ...
  }
  fetchBusinesses()
}, [])

3.使用useCallback()进行记忆

在这种情况下,如果你的函数中有依赖项,你必须将它们包含在useCallback依赖项数组中,如果函数的参数改变,这将再次触发useEffect。此外,这是一大堆样板文件……因此,只需像1中那样将函数直接传递给useEffect。useEffect (fetchBusinesses[])。

const fetchBusinesses = useCallback(() => {
  ...
}, [])
useEffect(() => {
  fetchBusinesses()
}, [fetchBusinesses])

4. 函数的默认实参

正如Behnam Azimi所说

这不是最佳实践,但在某些情况下可能有用。

useEffect((fetchBusinesses = fetchBusinesses) => {
   fetchBusinesses();
}, []);

5. 创建自定义钩子

创建一个自定义钩子,并在只需要运行一次函数时调用它。它可能更干净。你也可以在需要时返回一个回调来重置重新运行“初始化”。

// customHooks.js
const useInit = (callback, ...args) => {
  const [mounted, setMounted] = useState(false)
  
  const resetInit = () => setMounted(false)

  useEffect(() => {
     if(!mounted) {
        setMounted(true);
        callback(...args);
     }
  },[mounted, callback]);

  return [resetInit]
}

// Component.js
return ({ fetchBusiness, arg1, arg2, requiresRefetch }) => {
  const [resetInit] = useInit(fetchBusiness, arg1, arg2)

  useEffect(() => {
    resetInit()
  }, [requiresRefetch, resetInit]);

6. 禁用eslint的警告

禁用警告应该是您最后的手段,但是当您这样做时,最好是内联且显式地执行,因为未来的开发人员可能会感到困惑,或者在不知道linting关闭的情况下创建意外的错误

useEffect(() => {
  fetchBusinesses()
}, []) // eslint-disable-line react-hooks/exhaustive-deps

下一行禁用ESLint即可;

useEffect(() => {
   fetchBusinesses();
// eslint-disable-next-line
}, []);

通过这种方式,您使用它就像使用组件挂载(调用一次)一样。

更新

or

const fetchBusinesses = useCallback(() => {
 // Your logic in here
 }, [someDeps])

useEffect(() => {
   fetchBusinesses();
// No need to skip the ESLint warning
}, [fetchBusinesses]);

fetchBusinesses将在每次someDeps更改时被调用。