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

时间:2019-06-01 21:00:26

标签: reactjs react-hooks

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

我正在iuseEffect中调用另一个函数,但是保存文件后,它会自动将该函数添加到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));
  }

它一次又一次地运行。

5 个答案:

答案 0 :(得分:15)

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(()=>{...}, []);

答案 1 :(得分:1)

被接受的答案在某种程度上具有误导性。组件内部的定义函数显然会在每个渲染器上重新创建。但这并不意味着在使用useEffect挂钩时,它将在每个渲染中重新调用。

保存文件代码后的关键问题是您正在寻找getData。在每个渲染上重新创建它时,useEffect接受它作为更改,从而导致您在每个渲染上重新运行。 简单的解决方法是不观看getData。

但是显然,正如接受的答案所建议的那样。最好在组件外部分离函数,以免在每个渲染器上重新创建函数。

坦白说,如果我是你,我不会仅仅为获取定义函数:

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

答案 2 :(得分:0)

自从在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]);

  ...

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

答案 3 :(得分:0)

如果将getData函数移到useEffect内,则不必将其包括为依赖项,并且useEffect仅在query更改时运行。 / p>

答案 4 :(得分:0)

尝试将getData函数包装在useCallback钩子中并将其放在组件外部,因此当调用getData时,它将不会一直返回新函数,因此将阻止组件重新渲染