使用useDispatch Hook时如何等待Redux异步action返回响应
问题根因
你遇到的两个异常,本质是基于redux-thunk写的异步action没有把Promise的状态、返回值正确向外透传:
- 为啥组件then回调里拿到的结果一直是
undefined:axios请求成功后,你在对应的.then()回调里只做了dispatch登录action的操作,没写任何return语句,默认就会返回undefined,这个值顺着Promise链路传到了组件端。 - 为啥输错密码时反而先弹“success”:你在action内部写的
.catch()把所有请求错误全“接”住了,既没把错误重新往外抛,也没返回一个状态为reject的Promise。这种情况下外层永远感知不到请求失败,拿到的永远是状态为fulfilled的Promise,自然会先进自己的then回调弹success,等内部catch的逻辑跑完才弹账号错误的提示。
顺带提一句:你用redux-thunk的机制本来就是支持组件拿到异步action执行结果的——thunk会把你返回的那个异步函数里的所有return值、Promise状态全透传给dispatch的返回值,现在出问题纯是内部的Promise链路没打通。
修复方法
只需要调整异步action的内部逻辑,把成功的返回值、失败的状态往外透传就行,组件端的dispatch逻辑本身不用大改:
- 成功分支:dispatch完登录的同步action后,
return接口返回的响应数据,让外层拿到真实的成功结果 - 失败分支:在内部catch打完日志、弹完错误提示后,
throw捕获到的错误,让外层的Promise能正确进入失败状态
修正后的action代码:
export const fetchToken = (params) => { return (dispatch) => { const config = { headers: { 'Content-Type': 'application/x-www-form-urlencoded', }, }; return axios .post(`${baseUri}/api/token`, params, config) .then((res) => { dispatch({ type: LOGGED_IN, payload: res.data, }); // 把成功结果透传给外层 return res.data; }) .catch((err) => { console.log(err); alert('Provided username and password is incorrect'); // 重新抛出错误,让外层感知到请求失败 throw err; }); }; };
改完之后组件端的逻辑就完全符合预期了:
- 登录成功时:action dispatch完全局登录状态后,把token数据返回给组件的then回调,执行success提示
- 登录失败时:action内部先弹账号密码错误的提示,再把错误抛给组件的catch回调,执行对应的失败逻辑,不会再出现先弹success的时序错位。
小提醒:如果action内部已经做了错误提示,组件端的catch就别再写重复的alert了,可以根据需求把成功/失败的提示逻辑统一放在某一层,免得弹两次提示。
内容的提问来源于stack exchange,提问作者Kerry
相关产品推荐
相关产品推荐

