首页 > 解决方案 > 如何使用不可变的方式更新嵌套状态属性

问题描述

我正在尝试根据减速器中的 api 响应更新子记录。我当前的 redux 状态包含以下格式的数据:

const container = {
  data: [
    {
      id: "5e58d7bc1bbc71000118c0dc",
      viewName: "Default",
      children: [
        {
          id: "5e58d7bc1bbc71000118c0dd",
          description: "child1",
          quantity: 10
        },
        {
          id: "5e58d7bc1bbc71000118c0ff",
          description: "child2",
          quantity: 20
        },
        {
          id: "5e58d7bc1bbc71000118c0gg",
          description: "child3",
          quantity: 30
        }
      ]
    }
  ]
}

我从以下格式的 api 获取 child1 数据:

{
    id:"5e58d7bc1bbc71000118c0dd",
    description:"child1",
    quantity:20  // Quantity is updated 
}

如何以正确的方式更新 child1 的数量?

我正在使用不可变包。 https://www.npmjs.com/package/immutable

标签: reactjsreduximmutable.jssaga

解决方案


老实说,我认为没有理由使用 immutable.js,如果您不了解扩展语法或觉得它过于冗长,那么您可以使用这个 helper

const REMOVE = () => REMOVE;
const set = (object, path, callback) => {
  const setKey = (current, key, value) => {
    if (Array.isArray(current)) {
      return value === REMOVE
        ? current.filter((_, i) => key !== i)
        : current.map((c, i) => (i === key ? value : c));
    }
    return value === REMOVE
      ? Object.entries(current).reduce((result, [k, v]) => {
          if (k !== key) {
            result[k] = v;
          }
          return result;
        }, {})
      : { ...current, [key]: value };
  };
  const recur = (current, path) => {
    if (path.length === 1) {
      return setKey(
        current,
        path[0],
        callback(current[path[0]])
      );
    }
    return setKey(
      current,
      path[0],
      recur(current[path[0]], path.slice(1))
    );
  };
  return recur(object, path, callback);
};
const data = {
  name: [{ hello: 'world', stay: true }, 4],
  list: [1, 2, 3],
};
console.log(
  'setting nested value',
  set(data, ['name', 0, 'hello'], () => 'hello world')
    .name[0].hello
);
console.log(
  'doubling nested value',
  set(data, ['name', 1], x => x * 2).name[1]
);
console.log(
  'removing nested value',
  set(data, ['name', 0, 'hello'], REMOVE).name[0]
);
console.log(
  'adding to an array',
  set(data, ['list'], v => [...v, 4]).list
);
console.log(
  'mapping an array',
  set(data, ['list'], v => v.map(v => v * 8)).list
);
console.log(
  'data is not mutated',
  JSON.stringify(data, undefined, 2)
);

您没有发布任何有关如何将数据保存在状态中的代码,您是否使用了 immutable.js 类?如果你这样做了,那就告别 redux 开发工具并将状态记录到控制台。最好将其保留为数据对象(可使用 JSON.stringify 序列化)


推荐阅读