我已经研究了一些可能的方法,但是找不到与我正在使用的应用程序使用相同架构的架构。例如,React docs说我们应该有一个方法,该方法发出HTTP请求,然后在不同点(当请求开始时,收到响应时等等)调用操作。但是我们有另一种方法。我们使用一个动作来进行HTTP调用,然后分派结果。更确切地说,我的用例是这样:
// action to get resource A
getResourceA () {
return dispatch => {
const result = await axios.get('someLink');
dispatch({
type: GET_RES_A,
payload: result
});
};
}
// another action which needs data from resource A
getSomethingElseByIdFromA (aId) {
return async dispatch => {
const result = await axiosClient.get(`someLink/${aId}`);
dispatch({
type: GET_SOMETHING_BY_ID_FROM_A,
payload: result
});
};
}
如上所述,第二个动作需要第一个动作的数据。
现在,我知道执行此操作的两种方法:
getResourceA () {
return async dispatch => {
const result = await axios.get('someLink');
dispatch({
type: GET_RES_A,
payload: result
});
return result;
};
}
// and then, when using it, inside a container
async foo () {
const {
// these two props are mapped to the getResourceA and
// getSomethingElseByIdFromA actions
dispatchGetResourceA,
dispatchGetSomethingElseByIdFromA
} = this.props;
const aRes = await dispatchGetResourceA();
// now aRes contains the resource from the server, but it has not
// passed through the redux store yet. It's raw data
dispatchGetSomethingElseByIdFromA(aRes.id);
}
但是,我现在正在处理的项目希望数据首先通过存储-以防万一必须修改-并且只有在此之后才能使用。这把我带到了第二种做事方式:
getState
方法访问状态。aggregateAction () {
return await (dispatch, getState) => {
await dispatch(getResourceA());
const { aRes } = getState();
dispatch(getSomethingElseByIdFromA(aRes.id));
};
}
然后只需在容器中调用此操作即可。
我想知道第二种方法是否正确。我觉得仅仅为了在整个操作中访问它们而在redux存储中存储它们并不是很好。如果是这样,那么解决这个问题的更好方法是什么?
答案 0 :(得分:1)
我认为拥有/使用Epic
中的redux-observable
最适合您的用例。在使用SAME逻辑处理这些操作之前,它将首先使这些操作遍及化简器(与上述方法不同)。同样,使用一系列操作将使您可以在整个数据流中操作数据,而不必存储不必要的内容。当涉及到异步操作时,响应式编程和可观察的模式本身具有很多优势,这是比redux-thunk,sagas等imo更好的选择。
答案 1 :(得分:0)
我将研究使用自定义中间件(https://redux.js.org/advanced/middleware)。使用中间件可以使这种事情更容易实现。
类似的东西:
import {GET_RESOURCE_A, GET_RESOURCE_B, GET_RESOURCE_A_SUCCESS, GET_RESOURCE_A_ERROR } from '../actions/actionTypes'
const actionTypes = [GET_RESOURCE_A, GET_RESOURCE_B, GET_RESOURCE_A_SUCCESS, GET_RESOURCE_A_ERROR ]
export default ({dispatch, getState}) => {
return next => action => {
if (!action.type || !actionTypes.includes(action.type)) {
return next(action)
}
if(action.type === GET_RESOURCE_A){
try{
// here you can getState() to look at current state object
// dispatch multiple actions like GET_RESOURCE_B and/ or
// GET_RESOURCE_A_SUCCESS
// make other api calls etc....
// you don't have to keep stuff in global state you don't
//want to you could have a varaiable here to do it
}
catch (e){
} dispatch({type:GET_RESOURCE_A_ERROR , payload: 'error'})
}
}
}