我正在尝试使用thunk在一个动作中链接两个调用,但似乎无法正常工作。我需要第一个操作的ID值才能调用第二个操作。
动作如下:
export const getParentRecords = filterId => {
return (dispatch, getState) => {
let headers = {
filter_id: filterId
};
const request = axios({
method: "GET",
url: `https://myapi.com/v1/parent-records`,
headers: headers
});
dispatch({
type: GET_PARENT_RECORDS,
payload: request
});
};
};
export const getChildRecords = (parentId = null) => {
let url = `https://myapi.com/v1/child-records`;
if (parentId) {
url = `https://myapi.com/v1/child-records/?parent_id=${parentId}`;
}
return (dispatch, getState) => {
let headers = {
//etc...
};
const request = axios({
method: "GET",
url: url,
headers: headers
});
dispatch({
type: GET_CHILD_RECORDS,
payload: request
});
};
};
export const getAllRecords = filterId => {
return (dispatch, getState) => {
dispatch(getParentRecords(filterId);
let { parentRecords } = getState();
let defaultParent = parentRecords.filter(p => p.is_default === true)[0];
dispatch(getChildRecords(defaultParent.parent_id));
};
};
在调用组件中:
const mapStateToProps = state => {
return {
parentRecords: state.parentRecords,
childRecords: state.childRecords
};
};
export default connect(mapStateToProps, { getAllRecords })(MyComponent);
问题是;调度第一个动作似乎没有做任何事情。之后再调用getState()时,数据不存在。 getAllRecords中的parentRecords变量始终为空。
我真的不确定该怎么办。相当常见的情况,但尚未找到解决方法。
答案 0 :(得分:0)
我建议您使用另一个库来处理副作用,例如redux-saga
或redux-observable
,因为redux-thunk
非常原始。
Redux-saga是基于生成器的,并且势在必行。 Redux-observable是基于RxJS的声明性代码。 因此,选择更多您喜欢的东西。
https://redux-observable.js.org/
每个异步操作应具有三种操作类型,例如:GET_CHILD_RECORDS
,GET_CHILD_RECORDS_SUCCESS
和GET_CHILD_RECORDS_FAILURE
。
使用redux-saga,它看起来像这样:
动作创建者:
const getChildRecords = (parentId = null) => ({
type: GET_PARENT_RECORDS,
payload: parentId
});
然后您可以在saga生成器中处理此操作:
function rootSaga*() {
yield takeLatest(GET_PARENT_RECORDS, onGetParentRecords);
yield takeLatest(GET_PARENT_RECORDS_SUCCESS, onGetChildRecords);
}
function onGetParentRecords*({ payload: parentId }) {
try {
const parentRecords = yield call(apiCallFunctionHere, parentId);
yield put({
type: GET_PARENT_RECORDS_SUCCESS,
payload: parentRecords
});
} catch(error) {
yield put({
type: GET_PARENT_RECORDS_FAILURE,
error
});
}
}
function onGetChildRecords*({ payload: parentRecords }) {
const defaultParent = parentRecords.filter(p => p.is_default === true)[0];
try {
const childRecords = call(apiFunctionToFetchChildRecords, defaultParent);
yield put({
type: GET_CHILDREN_RECORDS_SUCCESS,
payload: parentRecords
});
} catch(error) {
yield put({
type: GET_CHILDREN_RECORDS_FAILURE,
error
});
}
}
答案 1 :(得分:0)
我对引入如此简单的框架不感兴趣。通勤回家后,一个念头打动了我。请让我知道优点/缺点。
新的getAllRecords函数:
export const getAllRecords = filterId => {
return (dispatch, getState) => {
let headers = {
// etc...
};
const request = axios({
method: "GET",
url: `https://myapi.com/v1/parent-records`,
headers: headers
});
request.then(result => {
if (result.status === 200) {
let parentRecords = result.data.payload;
let defaultParent = parentRecords.filter(p => p.is_default === true)[0];
dispatch({
type: GET_PARENT_RECORDS,
payload: parentRecords
});
dispatch(getChildRecords(defaultParent.parent_id));
}
});
};
};
这似乎为我提供了所需的一切。通过执行promise获取父记录,调度父子结果。