我可以在 useEffect 中调用单独的函数吗?

新手上路,请多包涵

我可以在 useEffect 中调用另一个单独的函数吗?

我在 useEffect 中调用另一个函数,但在保存文件后,它会自动将该函数添加到 useEffect 的数组参数中。

请参阅下面的代码以获得正确的理解。

保存文件前:

 useEffect(() => {
  getData()
  console.log("useEffect ran...");
}, [query]);

function getData() {
  fetch(`https://jsonplaceholder.typicode.com/${query}`)
  .then(response => response.json())
  .then(json => setData(json));
}

保存文件后:

 useEffect(() => {
  getData();
  console.log("useEffect ran...");
}, [getData, query]);

function getData() {
  fetch(`https://jsonplaceholder.typicode.com/${query}`)
    .then(response => response.json())
    .then(json => setData(json));
}

它一次又一次地运行。

原文由 Waseem Maya 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 837
2 个回答

由于您在 React 组件中声明了 getData 函数,它将在每次渲染时重新创建,因此效果的依赖关系在每次渲染时都会发生变化。这就是每次渲染都执行效果的原因。

为了防止这种情况,您应该在组件外部声明 getData 函数,然后传递查询。像这样:

 function getData(query) {
  return fetch(`https://jsonplaceholder.typicode.com/${query}`)
    .then(response => response.json());
}

function YouComponent({ query }) {
  ...
  useEffect(() => {
    getData(query).then(setData);
    console.log("useEffect ran...");
  }, [query]);

  ...

PS:我不确定eslint插件在这样做时是否会自动将getData添加到依赖项中,但即使这样做也不会受到伤害。

原文由 Sven Tschui 发布,翻译遵循 CC BY-SA 4.0 许可协议

TL;DR 使用 useCallback()


首先,让一个函数成为依赖是非常危险的。如果该函数导致状态更改,则随后的重新渲染将再次调用该函数(通过 useEffect)……无限循环开始。

正如此处许多人所建议的,您可以做的一件事是在 useEffect() 方法本身中创建函数。

  useEffect(() => {
    function getData() {
      fetch(`https://jsonplaceholder.typicode.com/${query}`)
        .then(response => response.json())
        .then(json => setData(json));
      }
    }

    getData();
    console.log("useEffect ran...");
  }, [query]);
}

或者简单地

 useEffect(() => {
    (() => {
       fetch(`https://jsonplaceholder.typicode.com/${query}`)
      .then(response => response.json())
      .then(json => setData(json)
     )();
  }, [query]);
}

话虽如此,有时您仍然希望在 useEffect 之外声明函数以进行 代码重用。这次您需要确保它不会在每次渲染期间重新创建。为此,您可以

  1. 在组件外部声明函数——这会迫使您将所有变量作为参数传递……这很痛苦

  2. 把它包在里面 useMemo()useCallback()

这是一个例子

    const getData = useCallback(()=>{...}, []);

原文由 DanielK 发布,翻译遵循 CC BY-SA 4.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进