我正在尝试下面的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
这里可以使用Void运算符。
而不是:
React.useEffect(() => {
async function fetchData() {
}
fetchData();
}, []);
or
React.useEffect(() => {
(async function fetchData() {
})()
}, []);
你可以这样写:
React.useEffect(() => {
void async function fetchData() {
}();
}, []);
它更干净,更漂亮。
异步效果可能会导致内存泄漏,因此在组件卸载时执行清理非常重要。在fetch的情况下,它可能是这样的:
function App() {
const [ data, setData ] = React.useState([]);
React.useEffect(() => {
const abortController = new AbortController();
void async function fetchData() {
try {
const url = 'https://jsonplaceholder.typicode.com/todos/1';
const response = await fetch(url, { signal: abortController.signal });
setData(await response.json());
} catch (error) {
console.log('error', error);
}
}();
return () => {
abortController.abort(); // cancel pending fetch request on component unmount
};
}, []);
return <pre>{JSON.stringify(data, null, 2)}</pre>;
}
在React提供更好的方法之前,你可以创建一个帮助器useEffectAsync.js:
import { useEffect } from 'react';
export default function useEffectAsync(effect, inputs) {
useEffect(() => {
effect();
}, inputs);
}
现在你可以传递一个async函数:
useEffectAsync(async () => {
const items = await fetchSomeItems();
console.log(items);
}, []);
更新
如果您选择这种方法,请注意这是一种糟糕的形式。当我知道这是安全的时候,我就会这样做,但这总是糟糕的方式和随意的。
悬疑的数据获取,仍处于实验阶段,将解决一些情况。
在其他情况下,您可以将异步结果建模为事件,以便您可以根据组件生命周期添加或删除侦听器。
或者你可以将异步结果建模为一个Observable,这样你就可以根据组件的生命周期订阅和取消订阅。