前言
刚开始学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内部逻辑的理解。