Как создать лицензионный стор в MobX для работы с древовидной структурой данных?

У меня есть древовидный массив объектов, который представлен следующим образом: 
<pre><code class="typescript">interface TreeItem {
  id: number;
  name: string;
  expanded: boolean;
  on: boolean;
  children?: TreeItem[];
}</code></pre> 

Мне нужно реализовать хранение данных в сторе, при этом он должен реагировать на изменения полей у своих потомков и родителей. Например, если все потомки имеют значение поля switch равным true, то родитель тоже должен автоматически устанавливать switch в true. Как лучше организовать такой стор и с помощью каких инструментов? Я пробовал использовать вложенные MobX сторы, но они оказались неудобными. Также я рассматривал mobx-state-tree, но не уверен, сможет ли он удовлетворить все мои требования.
  • 16 декабря 2024 г. 14:53
Ответы на вопрос 2
Для реализации лицензионного стора в MobX с использованием древовидной структуры данных, можно использовать MobX с обычными реактивными подходами. Однако, если вы ищете более структурированное решение, mobx-state-tree (MST) может сделать вашу работу более удобной и управляемой, особенно когда дело касается сложных деревьев и вложенных структур. 

Я предлагаю рассмотреть решение с помощью mobx-state-tree (MST), так как это позволяет легко управлять состоянием и встраивать реактивные зависимости. Ваша задача заключается в том, чтобы обновить состояние родителя на основе состояния его потомков.

Вот пример, как вы можете организовать такой стор с помощью MST:

### 1. Установка монорепозитория

Если вы ещё не установили mobx и mobx-state-tree, начните с установки необходимых библиотек:

```bash
npm install mobx mobx-state-tree
```

### 2. Определение модели данных

Создайте модель для вашего `TreeItem`:

```typescript
import { types, getParent } from "mobx-state-tree";

const TreeItem = types
  .model("TreeItem", {
    id: types.integer,
    name: types.string,
    expanded: types.boolean,
    on: types.boolean,
    children: types.optional(types.array(types.late(() => TreeItem)), [])
  })
  .views(self => ({
    get allChildrenOn() {
      return self.children.length > 0 
        ? self.children.every(child => child.on) 
        : false;
    }
  }))
  .actions(self => ({
    toggleOn() {
      self.on = !self.on;
      if (getParent(self).allChildrenOn) {
        getParent(self).on = true;
      } else {
        getParent(self).on = false;
      }
    },
    addChild(child) {
      self.children.push(child);
    },
    afterCreate() {
      const parent = getParent(self);
      if (parent && self.on) {
        if (parent.allChildrenOn) {
          parent.on = true;
        }
      }
    }
  }));

const TreeModel = types.model("TreeModel", {
  root: types.optional(TreeItem, { id: 0, name: "Root", expanded: false, on: false })
});
```

### 3. Создание экземпляра стора

Теперь вы можете создать экземпляр вашего стора и начать работать с ним:

```typescript
import { types } from "mobx-state-tree";

const store = TreeModel.create({ 
  root: { 
    id: 1, 
    name: "Root", 
    expanded: false, 
    on: false, 
    children: [] 
  } 
});

// Добавление дочернего элемента
const child1 = TreeItem.create({ id: 2, name: "Child 1", expanded: false, on: false });
store.root.addChild(child1);

// Изменение состояния дочернего элемента
child1.toggleOn(); // Устанавливает 'on' для Child 1 и проверяет состояние родительского элемента.
```

### 4. Реактивность

Так как MobX работает на основе реактивности, любые изменения в поле `on` будут автоматически отслеживаться, и изменения будут применяться к родительским элементам, если все требования выполняются (все потомки включены).

### Заключение

Использование mobx-state-tree в этом случае обеспечивает более чистую архитектуру, удобство управления состоянием, и реактивность, которая необходима для вашей древовидной структуры. Вы сможете легко расширять функциональность магазина и удовлетворять изменениям в структуре, обеспечивая при этом высокую производительность и читаемость кода.
В случае вложенных сторов on создаётся при помощи computed и никаких проблем нет. Ну и лучше никогда не писать children?: TreeItem[] , уж лучше также через computed понять - есть ли дочерние элементы. 

Что касается реагирования на изменения - нужны подробности, т.к. если речь только про on , то с ним не будет проблем.
Похожие вопросы