编写需要其他动作数据的redux动作的最佳方法是什么

时间:2019-04-10 08:36:35

标签: reactjs redux react-redux

我已经研究了一些可能的方法,但是找不到与我正在使用的应用程序使用相同架构的架构。例如,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
    });
  }; 
}

如上所述,第二个动作需要第一个动作的数据。

现在,我知道执行此操作的两种方法:

  1. 返回第一个操作的结果
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);
}

但是,我现在正在处理的项目希望数据首先通过存储-以防万一必须修改-并且只有在此之后才能使用。这把我带到了第二种做事方式:

  1. 提供“聚合”服务,并在操作完成后使用getState方法访问状态。
aggregateAction () {
  return await (dispatch, getState) => {
    await dispatch(getResourceA());
    const { aRes } = getState();
    dispatch(getSomethingElseByIdFromA(aRes.id));
  };
}

然后只需在容器中调用此操作即可。

我想知道第二种方法是否正确。我觉得仅仅为了在整个操作中访问它们而在redux存储中存储它们并不是很好。如果是这样,那么解决这个问题的更好方法是什么?

2 个答案:

答案 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'})
            }

        }

    }