在redux中的操作中访问状态

时间:2018-01-17 09:38:01

标签: javascript redux redux-thunk

许多链接和教程建议将动作创建器中的逻辑分组,以简化reducer逻辑。

想象一个简单的(规范化的)状态:

const initialState = {
  parent: {
    allIds: [0],
    byId: {
      0: {
        parentProperty: `I'm the parent`,
        children: [1, 2]
      }
    }
  },
  children: {
    allIds: [1, 2],
    byId: {
      1: {
        childrenProperty: `I'm the children`
      },
      2: {
        childrenProperty: `I'm the children`
      }
    }
  }
}

我现在会删除父母。由于只有父母提到孩子,我也会删除孩子。

我想象一个像这样的动作创作者:

function deleteParents(parentId) {
  return {type: 'DELETE_PARENT', payload: {parentId}};
}

function deleteChild(childId) {
   return {type: 'DELETE_CHILD', payload: {childId}};
}

目前,为了管理这个案例,我做了类似的事情(使用redux-thunk)

function deleteParentAndChildren(parentId) {
  return (dispatch, getState) {
    const childrenIds = myChildrenSelector(getState(), parentId);
    const deleteChildrenActions = childrenIds.map(deleteChild);
    const deleteParentAndChildrenAction = batchActions([
      deleteParents(parentId),
      ...deleteChildrenActions
    ], 'DELETE_PARENT_AND_CHILDREN');
    dispatch(deleteParentAndChildrenAction);
  }
}

通过这种方式,我将一个小动作组成一个大动作,而reducer逻辑非常简单,因为它只是删除一个对象中的一个键。

相反,我不喜欢使用redux-thunk(用于异步操作)来获取状态(这被认为是反模式)。

你们如何处理这类问题? 像redux-sage这样的工具可能有帮助吗?

2 个答案:

答案 0 :(得分:0)

您似乎遇到的问题似乎相当普遍,如果您的应用程序有点复杂,我建议使用redux-orm这有点难以理解然后集成但是一旦设置它只是抽象你所有的困难您实体之间的关系工作。

答案 1 :(得分:0)

我在这里有不同的看法。我这样做的方式是,我会在删除父节点时删除子节点而不是y调度child_delete动作。在reducer中删除parent时创建新状态时,此时,您可以访问该父级引用的子级,并从状态中删除这些子级。

此外,如果您仍希望单独分派操作,则可以将子代码从组件传递到操作。通过该操作,您可以发送两个不同的操作,删除父级和子级ID。

-----------编辑-------

// The initial application state
const initialState = {
  parent: {
    allIds: [0],
    byId: {
      0: {
        parentProperty: `I'm the parent`,
        children: [1, 2]
      }
    }
  },
  children: {
    allIds: [1, 2],
    byId: {
      1: {
        childrenProperty: `I'm the children`
      },
      2: {
        childrenProperty: `I'm the children`
      }
    }
  }
}

export default function batchManagement(state = initialState, action) {
  switch (action.type) {
    case 'DELETE_PARENT':  //assuming action.deleteParents = [0]
      //Here you have access to state, so you can change parents and children as well, and create a totally new state
    case 'DELETE_CHILDREN':
      //Return a new object for state
    default:
      return state;
  }
}