如何添加/删除使用normalizr生成的redux存储?

2024-01-14

查看示例README https://github.com/gaearon/normalizr:

鉴于“坏”结构:

[{
  id: 1,
  title: 'Some Article',
  author: {
    id: 1,
    name: 'Dan'
  }
}, {
  id: 2,
  title: 'Other Article',
  author: {
    id: 1,
    name: 'Dan'
  }
}]

添加新对象非常容易。我所要做的就是

return {
  ...state,
  myNewObject
}

在减速机中。

现在考虑到“好”树的结构,我不知道应该如何处理它。

{
  result: [1, 2],
  entities: {
    articles: {
      1: {
        id: 1,
        title: 'Some Article',
        author: 1
      },
      2: {
        id: 2,
        title: 'Other Article',
        author: 1
      }
    },
    users: {
      1: {
        id: 1,
        name: 'Dan'
      }
    }
  }
}

我想到的每一种方法都需要一些复杂的对象操作,这让我觉得我没有走在正确的轨道上,因为 Normalizr 应该让我的生活更轻松。

我在网上找不到任何以这种方式使用 Normalizr 树的示例。官方例子 https://github.com/rackt/redux/tree/master/examples/real-world不添加和删除,所以也没有帮助。

有人可以让我知道如何以正确的方式添加/删除标准化树吗?


以下内容直接来自 redux/normalizr 创建者的帖子here https://github.com/rackt/redux/issues/994:

所以你的状态看起来像:

{
  entities: {
    plans: {
      1: {title: 'A', exercises: [1, 2, 3]},
      2: {title: 'B', exercises: [5, 1, 2]}
     },
    exercises: {
      1: {title: 'exe1'},
      2: {title: 'exe2'},
      3: {title: 'exe3'}
    }
  },
  currentPlans: [1, 2]
}

你的减速器可能看起来像

import merge from 'lodash/object/merge';

const exercises = (state = {}, action) => {
  switch (action.type) {
  case 'CREATE_EXERCISE':
    return {
      ...state,
      [action.id]: {
        ...action.exercise
      }
    };
  case 'UPDATE_EXERCISE':
    return {
      ...state,
      [action.id]: {
        ...state[action.id],
        ...action.exercise
      }
    };
  default:
    if (action.entities && action.entities.exercises) {
      return merge({}, state, action.entities.exercises);
    }
    return state;
  }
}

const plans = (state = {}, action) => {
  switch (action.type) {
  case 'CREATE_PLAN':
    return {
      ...state,
      [action.id]: {
        ...action.plan
      }
    };
  case 'UPDATE_PLAN':
    return {
      ...state,
      [action.id]: {
        ...state[action.id],
        ...action.plan
      }
    };
  default:
    if (action.entities && action.entities.plans) {
      return merge({}, state, action.entities.plans);
    }
    return state;
  }
}

const entities = combineReducers({
  plans,
  exercises
});

const currentPlans = (state = [], action) {
  switch (action.type) {
  case 'CREATE_PLAN':
    return [...state, action.id];
  default:
    return state;
  }
}

const reducer = combineReducers({
  entities,
  currentPlans
});

那么这是怎么回事呢?首先,请注意状态已标准化。我们从来没有在其他实体内部拥有实体。相反,它们通过 ID 相互引用。因此,每当某些对象发生变化时,只有一个地方需要更新。

其次,请注意我们如何通过在计划缩减器中添加适当的实体并将其 ID 添加到 currentPlans 缩减器来对 CREATE_PLAN 做出反应。这个很重要。在更复杂的应用程序中,您可能有关系,例如计划减速器可以通过将新 ID 附加到计划内的数组来以相同的方式处理 ADD_EXERCISE_TO_PLAN。但如果练习本身更新了,计划减速器就不需要知道这一点,因为 ID 没有改变。

第三,请注意,实体减速器(计划和练习)有特别的条款来关注 action.entities。这是为了防止我们有一个包含“已知事实”的服务器响应,我们希望更新所有实体以反映该响应。要在分派操作之前以这种方式准备数据,您可以使用 normalizr。您可以在 Redux 存储库的“现实世界”示例中看到它的使用。

最后,请注意实体减速器的相似之处。您可能想编写一个函数来生成它们。这超出了我的回答范围——有时您想要更大的灵活性,有时您想要更少的样板。您可以查看“现实世界”示例减速器中的分页代码,以获取生成类似减速器的示例。

哦,我使用了 { ...a, ...b } 语法。它在 Babel 第 2 阶段作为 ES7 提案启用。它被称为“对象扩展运算符”,相当于编写 Object.assign({}, a, b)。

至于库,您可以使用 Lodash(但要注意不要变异,例如 merge({}, a, b} 是正确的,但 merge(a, b) 不是)、updeep、react-addons-update 或其他。但是,如果您发现自己需要进行深度更新,则可能意味着您的状态树不够平坦,并且您没有充分利用功能组合。即使是您的第一个示例:

case 'UPDATE_PLAN':
  return {
    ...state,
    plans: [
      ...state.plans.slice(0, action.idx),
      Object.assign({}, state.plans[action.idx], action.plan),
      ...state.plans.slice(action.idx + 1)
    ]
  };

可以写成

const plan = (state = {}, action) => {
  switch (action.type) {
  case 'UPDATE_PLAN':
    return Object.assign({}, state, action.plan);
  default:
    return state;
  }
}

const plans = (state = [], action) => {
  if (typeof action.idx === 'undefined') {
    return state;
  }
  return [
    ...state.slice(0, action.idx),
    plan(state[action.idx], action),
    ...state.slice(action.idx + 1)
  ];
};

// somewhere
case 'UPDATE_PLAN':
  return {
    ...state,
    plans: plans(state.plans, action)
  };
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何添加/删除使用normalizr生成的redux存储? 的相关文章

随机推荐