通过Props触发Action是否异步?及相关函数执行顺序问询
解答你的Redux Action相关问题
嘿,咱们一个个来拆解你的问题:
1. 通过Props触发Action是否为异步操作?
这个完全取决于你的Action本身的实现逻辑哦!
- 如果你的Action是同步Action(就是直接返回一个包含
type和payload的普通对象,用来直接更新Store),那通过Props触发它就是同步的——调用之后Store里的状态会立刻更新。 - 但如果你的Action里包含了异步逻辑(比如调用后端API、设置定时器这类),而且是用redux-thunk、redux-saga这类中间件来处理的,那触发它就是异步的——调用之后不会立刻更新Store,得等异步任务完成后才会触发状态更新。
举两个直观的例子:
同步Action(触发同步)
// Action Creator export const updateUserId = (id) => ({ type: 'UPDATE_USER_ID', payload: id }); // 组件内调用 this.props.updateUserId(456); // 这行代码执行完,Store里的userId已经是456了
异步Action(触发异步)
// 用redux-thunk实现的异步Action Creator export const getRemoteUserId = () => async (dispatch) => { // 模拟调用后端API const response = await fetch('/api/user/current/id'); const userId = await response.json(); // 异步任务完成后,才dispatch同步Action更新Store dispatch({ type: 'UPDATE_USER_ID', payload: userId }); }; // 组件内调用 this.props.getRemoteUserId(); // 这行代码执行完,Store里的userId还没更新,得等API请求返回后才会变
2. this.props.getRemotePrice()会等新userId存到Store后再触发吗?
默认情况下不会!
从方法名来看,getRemoteUserId()是远程获取数据的异步Action,调用它之后,JavaScript会直接往下执行getRemotePrice(),完全不会等它把新userId存到Store里。这时候getRemotePrice()拿到的大概率还是旧的userId,甚至可能拿不到有效ID,导致请求出错。
那怎么让getRemotePrice()在userId更新后再执行呢?给你几个常用的解决方案:
方案1:利用Promise链式调用(适合redux-thunk)
修改你的getRemoteUserId Action Creator,让它返回一个Promise,这样就能用await或者.then()来控制顺序:
// 修改后的getRemoteUserId export const getRemoteUserId = () => async (dispatch) => { const response = await fetch('/api/user/current/id'); const userId = await response.json(); dispatch({ type: 'UPDATE_USER_ID', payload: userId }); return userId; // 返回userId,让调用处能拿到异步操作的结果 }; // 组件内用async/await调用 async fetchUserData() { // 等getRemoteUserId的异步任务完成,userId更新到Store后 await this.props.getRemoteUserId(); // 再触发getRemotePrice this.props.getRemotePrice(); } // 在组件生命周期里调用这个方法 componentDidMount() { this.fetchUserData(); }
方案2:监听Store状态变化(通用方案)
在组件里监听userId的变化,当它更新时再触发getRemotePrice。以React类组件为例,用componentDidUpdate:
componentDidMount() { // 先触发获取userId的Action this.props.getRemoteUserId(); } componentDidUpdate(prevProps) { // 当userId从无到有,或者发生变化时 if (this.props.userId !== prevProps.userId && this.props.userId) { // 此时userId已经更新到Store了,触发获取价格的Action this.props.getRemotePrice(); } }
方案3:用中间件编排流程(适合redux-saga/redux-observable)
如果用的是redux-saga这类流程管理中间件,你可以直接在saga里编排异步流程:
import { call, put, takeLatest } from 'redux-saga/effects'; // 定义获取userId的saga function* fetchUserIdSaga() { const userId = yield call(fetch, '/api/user/current/id'); yield put({ type: 'UPDATE_USER_ID', payload: userId }); // 获取到userId后,直接调用获取价格的saga yield call(fetchPriceSaga, userId); } // 定义获取价格的saga function* fetchPriceSaga(userId) { const price = yield call(fetch, `/api/price?userId=${userId}`); yield put({ type: 'UPDATE_PRICE', payload: price }); } // 监听触发获取userId的Action export function* watchFetchUserId() { yield takeLatest('FETCH_USER_ID', fetchUserIdSaga); }
内容的提问来源于stack exchange,提问作者Blake
相关产品推荐
相关产品推荐

