递归地改变一棵树 isDisable boolean

Recursively change a tree isDisable boolean

给定一棵树:

type DataType = {
  id: string;
  access: 'view' | 'none';
  isDisabled: boolean;
  children: DataType[];
};

const Data: DataType = {
  id: '1',
  access: 'view',
  isDisabled: false,
  children: [
    {
      id: '2',
      access: 'view',
      isDisabled: false,
      children: [
        {
          id: '3',
          access: 'view',
          isDisabled: false,
          children: [],
        },
        {
          id: '4',
          access: 'view',
          isDisabled: false,
          children: [],
        },
      ],
    },
    {
      id: '5',
      access: 'view',
      isDisabled: false,
      children: [],
    },
  ],
};

我想做的是当节点的访问权限发生变化时,isDisabled 布尔值将根据以下规则发生变化:

如果访问权限为'view',isDisabled 将保持为 false 如果access为'none',则当前节点的isDisabled为false,但其children的isDisabled为true。

这是我现在拥有的:

export const find = (data, selectedId, access) => {
  if (!selectedId || !access) {
    return data;
  }

  if (data.id === selectedId) {
    data = changeAccess(data, selectedId, access);
    return data;
  }
  data.children.map((child) => find(child, selectedId, access));

  return data; // this is where the problem lies, but not sure how to fix it
};

export const changeAccess = (data, selectedId, access) => ({
  ...data,
  access: access,
  isDisabled: data.id !== selectedId && access !== 'view' ? true : false, // this toggles isDisabled
  children: data.children?.map((child) =>
    changeAccess(child, selectedId, access)
  ),
});

所以当我打电话给 'find'

const result = find(Data, '2', 'none');

结果应等于以下内容:

const DataAfter: DataType = {
  id: '1',
  access: 'view',
  isDisabled: false,
  children: [
    {
      id: '2',
      access: 'none',
      isDisabled: false,
      children: [
        {
          id: '3',
          access: 'none',
          isDisabled: true,
          children: [],
        },
        {
          id: '4',
          access: 'none',
          isDisabled: true,
          children: [],
        },
      ],
    },
    {
      id: '5',
      access: 'view',
      isDisabled: false,
      children: [],
    },
  ],
};

您在代码中突出显示的部分:

  data.children.map((child) => find(child, selectedId, access));

  return data; // this is where the problem lies, but not sure how to fix it

... 没有使用 returned 的数组 .map()。因此 data 以其原始状态 returned。

当映射的子数组有一个或多个新对象时,您应该return一个新对象:

  const children = data.children.map((child) => find(child, selectedId, access));
  if (data.children.some((child, i) => child !== children[i])) {
    data = {
      ...data,
      children
    };
  }

  return data;