Mobx-state-tree Clone также изменяет исходный элемент?

#mobx-react #mobx-state-tree

#mobx-реагировать #mobx-state-tree

Вопрос:

У меня есть следующий фрагмент модели:

 nodeOrigin: types.maybe(types.reference(nodeState)),
node: types.maybe(nodeState),
  

И я начинаю редактировать узел с помощью следующей функции (исходный узел, который я сохранил, чтобы его можно было использовать в функции отмены ()):

 startEditing(node) {
    self.nodeOrigin = node;
    self.node = clone(node);
}
  

И в моем методе рендеринга узел редактирования используется следующим образом:

 <form className="form">
     <TextField margin='dense' value={getStore().node["name"]} />
</form>
  

Но когда я меняю имя и печатаю содержимое как узла, так и исходного узла, у них обоих измененное имя. Исходный узел должен содержать исходное имя. Что я делаю не так?

Комментарии:

1. Рассмотрите возможность создания интерактивного элемента на codesandbox.io/dashboard

Ответ №1:

types.reference привязано к types.identifier . То, что вы, вероятно, неправильно понимаете здесь, это то, что types.reference ссылается types.identifier на свойство данного узла, а не на сам узел.

Когда вы clone не изменяете id исходный узел. types.reference разрешается «на лету» из кэша идентификаторов с помощью заданного id , поэтому он всегда будет ссылаться на узел с заданным id .

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

В качестве альтернативы вы могли бы сделать снимок узла, который хотите клонировать, вручную обновить types.identifier свойство и создать из него новый узел. Что-то вроде:

 const cloneWithNewId = (node, id) =>
      getType(node).create(Object.assign({}, getSnapshot(node), { id }));
  

Комментарии:

1. Хммм, ваше последнее предложение не работает, что я делаю: получаю snapshot(self.node).id = 123 и это приводит к: Не удается присвоить свойству ‘id’ объекта ‘#<Object>’ только для чтения. Есть идеи, что идет не так?

2. getSnapshot создает замороженный объект, поэтому вместо того, чтобы изменять его напрямую, создайте новый: Object.assign({}, getSnapshot(node), { id: 'new id })