小编典典

对useEffect中的异步函数的React Hook警告:useEffect函数必须返回清除函数,否则不返回任何内容

reactjs

我正在尝试useEffect示例,如下所示:

useEffect(async () => {

    try {

        const response = await fetch(`https://www.reddit.com/r/${subreddit}.json`);

        const json = await response.json();

        setPosts(json.data.children.map(it => it.data));

    } catch (e) {

        console.error(e);

    }

}, []);

我在控制台中收到此警告。但是对于我认为的异步调用,清理是可选的。我不确定为什么会收到此警告。链接沙箱示例。https://codesandbox.io/s/24rj871r0p
在此处输入图片说明


阅读 1281

收藏
2020-07-22

共1个答案

小编典典

我建议在这里看看Dan
Abramov(React核心维护者之一)的答案

我认为您正在使它变得比所需的更加复杂。

function Example() {
  const [data, dataSet] = useState<any>(null)

  useEffect(() => {
    async function fetchMyAPI() {
      let response = await fetch('api/data')
      response = await response.json()
      dataSet(response)
    }

    fetchMyAPI()
  }, [])

  return <div>{JSON.stringify(data)}</div>
}

从长远来看,我们会阻止这种模式,因为它会鼓励比赛条件。例如-
在通话开始和结束之间可能会发生任何事情,并且您可能会获得新的道具。相反,我们建议使用Suspense进行数据提取,看起来更像

const response = MyAPIResource.read();

并没有影响。但是与此同时,您可以将异步内容移到一个单独的函数中并进行调用。

您可以在此处阅读更多有关实验性悬念的信息


如果要在eslint之外使用函数。

 function OutsideUsageExample() {
  const [data, dataSet] = useState<any>(null)

  const fetchMyAPI = useCallback(async () => {
    let response = await fetch('api/data')
    response = await response.json()
    dataSet(response)
  }, [])

  useEffect(() => {
    fetchMyAPI()
  }, [fetchMyAPI])

  return (
    <div>
      <div>data: {JSON.stringify(data)}</div>
      <div>
        <button onClick={fetchMyAPI}>manual fetch</button>
      </div>
    </div>
  )
}

与useCallback useCallback一起使用沙盒

import React, { useState, useEffect, useCallback } from "react";

export default function App() {
  const [counter, setCounter] = useState(1);

  // if counter is changed, than fn will be updated with new counter value
  const fn = useCallback(() => {
    setCounter(counter + 1);
  }, [counter]);

  // if counter is changed, than fn will not be updated and counter will be always 1 inside fn
  /*const fnBad = useCallback(() => {
      setCounter(counter + 1);
    }, []);*/

  // if fn or counter is changed, than useEffect will rerun
  useEffect(() => {
    if (!(counter % 2)) return; // this will stop the loop if counter is not even

    fn();
  }, [fn, counter]);

  // this will be infinite loop because fn is always changing with new counter value
  /*useEffect(() => {
    fn();
  }, [fn]);*/

  return (
    <div>
      <div>Counter is {counter}</div>
      <button onClick={fn}>add +1 count</button>
    </div>
  );
}
2020-07-22