【问题标题】:Access the state in an action in redux在 redux 中访问 action 中的状态
【发布时间】:2018-06-26 03:21:40
【问题描述】:

许多链接和教程建议将 action creators 中的逻辑分组,以简化 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 这样的工具有帮助吗?

【问题讨论】:

  • 您能更清楚地说明您要达到的目标吗?所以你想要一种方法来删除父级和所有相应的子级?
  • 没错,很抱歉不清楚。我也会保留很少(和可组合的)动作
  • 您是否考虑过重新评估您的数据结构?我会考虑将父键和子键作为数组,其中包含对象。每个对象都有它的结构和一个引用 ID。父对象可以有一个子数组,其中包含相关子对象的 id。我将使用 redux-thunk 进行异步操作来调用父级的删除,成功删除的最终操作调用可能会触发另一个异步操作来删除具有与已删除的父级相关的 ref id 的任何子级。跨度>

标签: javascript redux redux-thunk


【解决方案1】:

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

【讨论】:

    【解决方案2】:

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

    此外,如果您仍想单独调度操作,您可以将子 ID 从组件传递到操作。通过该操作,您可以分派两个不同的操作,删除父 ID 和子 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;
      }
    }
    

    【讨论】:

    • 是的,你是对的。但是要找到孩子的身份,我需要状态。这意味着我需要 redux-thunk 作为解决方法(即使是做同步操作)。
    • 嗨@Epitouille,我猜你没听错。当您正确使用 reducer 方法时,您可以访问状态。请看我编辑的答案
    • 哦,是的,我没听错。您选择的问题是我的完整减速器是:combineReducer({parent, children}); 所以我从不访问我的应用程序的完整状态。我只吃一片。 :)
    • 我的错。没有想到那个选项。让我想想还能做什么。那么在这种情况下,您是否可以访问组件中父级引用的子级 ID。如果你有childrenids,你可以分别从组件中调度parent_delete和children_delete
    • 现在,我使用原始问题中描述的 redux-thunk 方法。可能不是最好的解决方案,但效果很好。如果孩子有孩子(孙子),就会出现另一个问题。如果我解决了孩子,我只能拥有大孩子的身份。在所有情况下,我都需要某个地方的完整状态。最好的解决方案可能是@guillaumepotier 答案和使用以及 ORM。
    猜你喜欢
    • 2018-12-23
    • 2020-06-17
    • 1970-01-01
    • 2022-01-27
    • 1970-01-01
    • 2023-03-22
    • 2023-03-23
    • 2020-10-26
    • 2019-01-19
    相关资源
    最近更新 更多