Как моделировать рекурсивно вложенные данные в состоянии - PullRequest
0 голосов
/ 07 апреля 2020

У меня есть структура данных типа:

export interface IGroup {
  id: number;
  name: string;
  groupTypeId: number;
  items: IItem[];
  groups: IGroup[];

}

, которая рекурсивно представляет многие-многие отношения между «Группой» и «Группой», а также «Группой» и «Элементом». Группы состоят из элементов и дочерних групп. Элемент наследуется от простого типа и других метаданных, но не может иметь дочерних элементов. Одна группа представляет собой вершину иерархии.

В настоящее время у меня есть компоненты, перехватчики и т. Д. c, чтобы рекурсивно взять одну группу и создать форму редактирования / создания, как показано ниже:

Component to display recursive model

У меня есть эта форма, «работающая» с тестовыми данными для получения стандартного вывода данных, как показано ниже при сохранении:

{
  "1-1": {
    "name": "ParentGroup",
    "groupType": 2
  },
  "2-4": {
    "name": "ChildGroup1",
    "groupType": 1
  },
  "2-9": {
    "name": "ChildGroup2",
    "groupType": 3
  },
  "2-1": {
    "itemType": "FreeForm",
    "selectedName": "Testing",
    "selectedClass": 5
  },
  "2-2": {
    "itemType": "FreeForm",
    "selectedName": "DisplayTest",
    "selectedClass": 5
  },
  "3-4": {
    "itemType": "EnumValue",
    "selectedItem": {
      "id": 12900503,
      "name": "TRUE"
    }
  },
  "3-5": {
    "itemType": "EnumValue",
    "selectedItem": {
      "id": 12900502,
      "name": "FALSE"
    }
  },
  "3-9": {
    "itemType": "FreeForm",
    "selectedName": "Test",
    "selectedClass": 5
  },
  "3-10": {
    "itemType": "FreeForm",
    "selectedName": "Tester",
    "selectedClass": 5
  },
  "3-11": {
    "itemType": "FreeForm",
    "selectedName": "TestTest",
    "selectedClass": 5
  }
}

«Ключом» к этим объектам являются столбец и строка сетки, так как других гарантированных уникальных идентификаторов нет (если пользователь редактирует, то ожидается, что группы имеют идентификаторы в БД, но не если пользователь добавляет новые группы в форму. В противном случае имя является формой ввода, которую можно изменить. ) Это имеет смысл, и моделировать ключи таким способом легко. Если в иерархию добавляется другая группа или элемент, ее можно добавить с помощью столбца и строки.

Проблема, с которой я столкнулся, заключается в том, что мне бы хотелось иметь кнопку добавления, которая добавляла бы к группирует элементы или группирует массивы, чтобы можно было создавать новые строки в иерархии. Мои формы должны обрабатывать эти новые записи. Пример.

"1-1": {
  groups: [..., {}],
  items: [..., {}]
}

Но единственная структура данных, которую я имею, - это IGroup, которая глубоко вложена. Это не хорошо для использования в качестве состояния и для добавления в это глубоко вложенное состояние.

Другая проблема, с которой я столкнулся, заключается в том, что мне нужно иметь возможность сопоставить элементы и группы с их положением, чтобы я мог перевести на соответствующие базы данных «многие ко многим» и вставьте новые группы / элементы.

Предлагаемое решение: я думал, что вместо того, чтобы брать группу в мои рекурсивные компоненты, я мог бы вместо этого создать нормализованные объекты для использования для хранения состояния. Я хотел бы иметь один объект с ключом столбца-строки, который будет содержать все группы. Еще один ключ с колонкой-строкой для хранения всех элементов. Тогда я думаю, что мне понадобятся еще два объекта, чтобы удерживать многие-многие отношения, такие как Группировка в Группу и Группировка в Элемент.

После того, как я получу данные из формы, я надеюсь, что смогу l oop через эти объекты состояния найдите иерархию таким образом и отправьте необходимые данные в базу данных.

Я вижу, что это много структур данных для хранения этих данных, и я не был уверен, что это лучший способ для достижения sh это учитывая мою модельную структуру. Я только начал использовать Redux Toolkit, так что я немного знаком с редукторами, но недостаточно, чтобы понять, как я могу применить их здесь, чтобы помочь мне. Я действительно пытался понять это, любая помощь или руководство, чтобы облегчить это, будет высоко ценится.

1 Ответ

1 голос
/ 10 апреля 2020

Go с нормализацией. Каждая сущность, имеющая единственный источник истины, значительно облегчает чтение и запись состояния.

Для этого попробуйте normalized-reducer . Это простой редуктор высшего порядка с низкой кривой обучения.

Вот рабочий пример CodeSandbox , реализующий составное дерево группы / элемента, очень похожее на вашу проблему.

По сути, вы должны определить схему своего дерева:

const schema = {
  group: {
    parentGroupId: { type: 'group', cardinality: 'one', reciprocal: 'childGroupIds' },
    childGroupIds: { type: 'group', cardinality: 'many', reciprocal: 'parentGroupId' },
    itemIds: { type: 'item', cardinality: 'many', reciprocal: 'groupId' }
  },
  item: {
    groupId: { type: 'group', cardinality: 'one', reciprocal: 'itemIds' }
  }
};

Затем передать ее в функцию верхнего уровня библиотеки:

import normalizedSlice from 'normalized-reducer';

export const {
  emptyState,
  actionCreators,
  reducer,
  selectors,
  actionTypes,
} = normalizedSlice(schema);

Затем подключить reducer в ваше приложение (работает как с React useReducer, так и с редукторами хранилища Redux) и используйте selectors и actionCreators для чтения и записи состояния.

...