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

我正在尝试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 在此处输入图片说明

ItachiGreen2020/03/14 18:18:26

尝试

const MyFunctionnalComponent: React.FC = props => {
  useEffect(() => {
    // Using an IIFE
    (async function anyNameFunction() {
      await loadContent();
    })();
  }, []);
  return <div></div>;
};

小哥Gil2020/03/14 18:18:26

对于其他读者,该错误可能是由于没有括号包装异步函数的事实引起的:

考虑异步函数initData

  async function initData() {
  }

此代码将导致您的错误:

  useEffect(() => initData(), []);

但是,这一点不会:

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

(注意initData()的方括号

前端LEYLEY2020/03/14 18:18:26

我通读了这个问题,并认为答案中没有提到实现useEffect的最佳方法。假设您有一个网络通话,并且希望在收到回复后立即采取措施。为了简单起见,让我们将网络响应存储在状态变量中。可能需要使用操作/缩减程序来通过网络响应来更新商店。

const [data, setData] = useState(null);

/* This would be called on initial page load */
useEffect(()=>{
    fetch(`https://www.reddit.com/r/${subreddit}.json`)
    .then(data => {
        setData(data);
    })
    .catch(err => {
        /* perform error handling if desired */
    });
}, [])

/* This would be called when store/state data is updated */
useEffect(()=>{
    if (data) {
        setPosts(data.children.map(it => {
            /* do what you want */
        }));
    }
}, [data]);

参考=> https://reactjs.org/docs/hooks-effect.html#tip-optimizing-performance-by-skipping-effects

达蒙西里2020/03/14 18:18:26

当您使用诸如

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);
    }
}

它返回一个useEffectPromise,并且不希望回调函数返回Promise,而是期望不返回任何内容或返回一个函数。

作为警告的解决方法,您可以使用自调用异步功能。

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

或使其更清晰,您可以定义一个函数然后调用它

useEffect(() => {
    async function fetchData() {
        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);
        }
    };
    fetchData();
}, []);

第二种解决方案将使其更易于阅读,并且将帮助您编写代码以在触发新请求时取消先前的请求或将最新的请求响应保存在状态中

工作代码和邮箱