【问题标题】:How do I avoid an infinite loop in useEffect when using Typescript?使用 Typescript 时如何避免 useEffect 中的无限循环?
【发布时间】:2021-12-04 19:17:51
【问题描述】:

我正在发送这样的请求:

function getDecks() {
    return Axious.get(urlGetAllDecks).then((response) => response.data);
}

然后我使用一个功能组件,我尝试通过从我的 database.js 文件中调用上述函数来初始化状态。但是,useEffect 块被调用了无数次。

export interface DeckSelectionState {
  id: number;
  module: number;
  title: string;
  description: string;
  dateCreated: string;
  reviewStatus: number;
  nextReviewDate: string;
}

const DeckSelection: React.FunctionComponent = () => {
  const [decks, setDecks] = React.useState<DeckSelectionState[]>([]);

  React.useEffect(() => {
    database.getDecks().then((response) => {
      setDecks(response);
    });
  });

知道如何解决这个问题吗?

【问题讨论】:

    标签: reactjs typescript express axios react-hooks


    【解决方案1】:

    为了确保useEffect 只执行一次,您必须通过传递一个空数组来指定一个空依赖列表。

    代码应如下所示:

    React.useEffect(() => {
      database.getDecks().then((response) => {
        setDecks(response);
      });
    }, []);
    

    useEffect 的第二个参数是依赖数组,它指定了效果所依赖的值的列表,这意味着只有当其中一个值发生变化时才会执行效果。通过指定数组[],你基本上是在说效果不依赖于任何值,应该只执行一次,而不指定依赖数组意味着效果依赖于所有的道具和状态。

    来自documentation

    如果你想运行一个效果并且只清理一次(在挂载和卸载时),你可以传递一个空数组([])作为第二个参数。这告诉 React 你的效果不依赖于任何来自 props 或 state 的值,所以它永远不需要重新运行。这不是作为特殊情况处理的——它直接遵循依赖数组的工作方式。 如果传递一个空数组 ([]),则效果内的 props 和 state 将始终具有它们的初始值。虽然将 [] 作为第二个参数传递更接近于熟悉的 componentDidMount 和 componentWillUnmount 心理模型,但通常有更好的解决方案来避免过于频繁地重新运行效果。另外,不要忘记 React 会延迟运行 useEffect 直到浏览器绘制完成,所以做额外的工作不是问题。

    为什么不指定 [setDecks] 作为依赖数组?

    setDecks是设置你使用过的useState钩子对应的状态的函数。虽然您可以将它添加到依赖数组中,因为效果似乎“依赖”它,但它永远不会改变,因此它永远不会影响效果。 来自documentation on useState

    React 保证 setState 函数的身份是稳定的,并且不会在重新渲染时改变。这就是为什么从 useEffect 或 useCallback 依赖列表中省略是安全的。

    【讨论】:

    • setDecks 应该进入依赖数组(但不会导致重新渲染)
    • 谢谢@jsejcksn。我错过了,我更新了我的答案。
    • 您对[] 是正确的,将setDecks 作为依赖项在这里没有做任何事情,.. decks 也许,但前提是decks 用于运行效果,但是在这种情况下,它不是.. @jsejcksn 您可能想查看依赖项的作用。我将 Doc 归咎于 React 的网站,因为它似乎暗示永远不应使用 [],但 OP 发布的效果与任何道具或状态无关。
    • 感谢@Keith 指出这一点。我很困惑地认为setDecks 是一个可以改变的道具,我已经更新了我的答案来解释为什么从依赖列表中省略它是安全的。
    猜你喜欢
    • 1970-01-01
    • 2021-03-07
    • 2020-10-16
    • 2020-03-28
    • 1970-01-01
    • 2019-05-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多