useEffect中async/await写法try块内变量为undefined,改用Promise则正常
问题产生原因
核心问题是变量名重复导致的块级作用域屏蔽+暂时性死区,和zustand持久化、Next.js本身没有关联:
- 你在async/await写法的try块内部,写了
const { returnedData: someData, someOtherReturnedData } = response的逻辑,相当于在try这个块级作用域内,重新声明了一个和外层同名的someData变量。 - JS中
let/const声明的变量存在「变量提升」,但会进入暂时性死区:变量声明会被提升到当前块级作用域的顶部,但在实际赋值语句执行前,访问该变量都会返回undefined。你在try块开头打印someData的时候,内层声明的someData已经覆盖了外层的同名变量,但还没有执行到赋值语句,所以打印结果是undefined。 - 为什么Promise链式调用写法正常?因为你调用
get请求、拼接url时还没进入.then的作用域,访问的是外层的someData;而.then内部的同名someData声明只在.then的块级作用域内生效,不会影响到请求发送阶段的取值。
解决方法
- 首先修改try块内解构的变量名,不要和外层的
someData重名,避免作用域屏蔽:
// 把解构赋值的别名改成其他名称即可 const { returnedData: newSomeData, someOtherReturnedData } = response setDataInSessionStore({ someData: newSomeData, someOtherReturnedData, })
- 修正useEffect的不规范写法:
- 不要直接把async函数传给useEffect,因为useEffect期望返回值是清理函数或者undefined,async函数返回的Promise会导致React运行警告。正确写法是在useEffect内部声明async函数再调用。
- 补全useEffect的依赖数组,把用到的外部变量(如someData、router、setDataInSessionStore等)加入依赖,避免闭包陷阱。
修正后的代码示例:
useEffect(() => { const fetchData = async () => { if (!someData) return try { console.log('inside try block', someData) // 现在会正常打印外层的someData值 const response = await get(apiUrl('urlInObject') + `${someData}`, { someData, }) // 修改变量名避免重名 const { returnedData: newSomeData, someOtherReturnedData } = response setDataInSessionStore({ someData: newSomeData, someOtherReturnedData, }) showNotification({ type: 'success', message: `The operation was successful.`, }) router.push('/pages/other-page') } catch (error) { if (error.code === 400) { showNotification({ message: `${error.data}` }) } if (error.code === 404) { showNotification({ message: `'${someData}' is not valid. Please try again.`, }) router.push('/pages/different-page') } console.error('ERROR: ', error) } } fetchData() }, [someData, router, setDataInSessionStore, showNotification])
内容的提问来源于stack exchange,提问作者Tara
相关产品推荐
相关产品推荐

