前言
刚开始学react写过类似下面的代码,就是想直接在useEffect中使用async/await。然后浏览器就会报错如下图:
useEffect(async () => {
const res = await Promise.resolve({ code: 200, mes: '' });
}, [])
报错的意思: useEffect 期望接受一个同步的函数作为参数,但 async 函数实际上返回的是一个 Promise。useEffect应该返回的是一个销毁函数,这里第一个参数使用了async,返回就是promise,会导致销毁函数报错。
react为什么这么做
我们都知道useEffect是很重要的一个hooks,可以执行一些副作用操作,它可以完成一些在class组件中一些生命周期函数的职责。如果返回值是异步的,那我们可能就无法预知代码的执行情况,很容易出现难以定位的bug,所以React就直接限制了useEffec回调函数中不支持async/await。
useEffect
期望一个函数,而async () => {}
返回的是一个Promise。这样的使用会造成不匹配,因为useEffect
不支持直接返回Promise,它需要一个函数,且该函数可以返回另一个函数用于清理。
这就是为什么像useEffect(async () => {}, [])
这样的用法会导致错误。JavaScript引擎会指出传递给useEffect
的参数不符合其要求。
useEffect如何支持async/await
方式一:
可以在useEffect
内部定义一个async
函数,然后在其中使用async/await
语法来处理异步操作。
useEffect(() => {
const fetchData = async () => {
try {
const result = await someAsyncOperation();
// 进行其他操作,比如更新 state
} catch (error) {
// 处理错误
}
};
fetchData();
// 你可以选择返回一个清除函数,如果需要清理操作的话
return () => {
// 清理操作
};
}, [/* 依赖 */]);
注意,在useEffect
内部定义一个async
函数并不会改变useEffect
的行为,它仍然会被当做同步操作处理。这里,我们只是利用了async/await
语法来处理异步操作,但useEffect
本身仍需遵循其原有的规则和生命周期。
方式二:
你可以直接在 useEffect
中使用 IIFE(立即调用函数表达式)来处理异步操作。这种方法可以让你在 useEffect
中立即执行异步函数。
useEffect(() => {
(async () => {
try {
const result = await someAsyncOperation();
// 处理结果
} catch (error) {
// 处理错误
}
})();
// 可选:返回一个清理函数
return () => {
// 清理操作
};
}, [/* 依赖 */]);
自定义useAsyncEffect 函数
当涉及到在useEffect
中使用异步操作时,可以创建自定义的useAsyncEffect
钩子函数,返回一个清理函数,类似于内置的useEffect
。在异步操作结束后执行清理操作,这个自定义钩子可以管理异步逻辑并使其更清晰易用。
const useAsyncEffect = (effectFunction, cleanupFunction, dependencies) => {
useEffect(() => {
effectFunction();
return cleanupFunction;
// eslint-disable-next-line react-hooks/exhaustive-deps
}, dependencies);
};
这样的话可以在调用 useAsyncEffect
时传入异步函数、清理函数和依赖项数组。在内部使用 useEffect
,并确保在 useEffect
中返回清理函数,以便在组件卸载或依赖项变更时执行清理操作。
使用:
useAsyncEffect(
async () => {
try {
const result = await fetchData();
// 处理获取的数据
} catch (error) {
// 处理错误
}
},
() => {
// 执行清理操作
},
[/* dependencies */]
);
这种方式能够在传入异步操作和清理函数的同时,仍然利用 useEffect
的特性进行管理。
这useAsyncEffect只是一个简单的自定义封装,使用还需对useEffect内部逻辑的理解。