如何更新 Mobx 可观察数组中的对象

How to update object in Mobx observable array

Codesandbox问题: https://codesandbox.io/s/serverless-thunder-6gj04?file=/src/store.js

我有以下商店:

class PersonStore {
  persons = [];

  constructor() {
    makeAutoObservable(this, {}, { autoBind: true });
  }

  *fetchPersons() {
    const response = yield fetch(
      "https://random-data-api.com/api/users/random_user?size=5"
    );

    this.persons = yield response.json();
  }
}

export default new PersonStore();

现在,我想更新人员列表中的人员。

当我像这样更新数组内项目的单个字段时,它按预期工作并且 UI 更新:

  update(id) {
    let updated = this.persons.find((p) => p.id === id);

    // This works...
    updated.first_name = "FOO";
  }

但是,将来我想将更复杂的更新数据传递到此函数中。所以我的想法是基本上用列表中的更新值分配一个全新的对象。

不幸的是,这并没有像我预期的那样工作:

  update(id) {
    let updated = this.persons.find((p) => p.id === id);

    // This does not work...
    const dummy_person = { first_name: 'foo', last_name: 'bar', id: 99 }
    updated = dummy_person
  }

我的第一个猜测是这不起作用,因为数组中的对象不是“普通对象”而是可观察对象。所以我为这些人创建了一个模型:

class Person {
  id = null;
  first_name = "";
  last_name = "";

  constructor() {
    makeAutoObservable(this);
    this.first_name = "FOO";
    this.last_name = "BAR";
  }
}

...但这仍然不起作用...

  update(id) {
    let updated = this.persons.find((p) => p.id === id);

    // This does not work...
    const dummy_person = new Person()
    updated = person
  }

如何用包含更新数据的对象“替换”数组中的对象?

正如@Tholle 在评论中所说,您只是在更新局部变量,而不是实际对象。

简单来说,这就是您的 update 函数中发生的事情:

  1. let updated = this.persons.find((p) => p.id === id); - 您创建局部变量 updated 并为其分配一些对象(人)

  2. const dummy_person = { first_name: 'foo', last_name: 'bar', id: 99 } - 您创建虚拟对象并将其分配给本地 dummy_person 常量

  3. updated = dummy_person - 此处您将 ​​dummy_person 值分配给 updated 变量。基本上你只重新分配 updated 变量的值,你不是在改变人对象,而只是改变到什么值 updated 变量点。

有时人们用盒子来解释它,比如想象 updated 是一个盒子,一开始你把 person 放在里面,然后你改变主意把 dummy_person 放在里面,但实际 person 没有改变。

那你能做什么?

正如@Tholle 所说,您可以使用splice 来更改persons 数组,它基本上会丢弃旧的人并插入新的人。

或者如果你真的想更新老人,你可以使用 Object.assign(updated, dummy_person)

或者你可以使用map(尽管它会重新分配整个数组,有时可能是不必要的):

  update(id) {
    const dummy_person = { first_name: 'foo', last_name: 'bar', id: 99 };

    this.persons = this.persons.map(person => person.id === id ? dummy_person : person);
  }

你能做的很多,取决于你做什么。最主要的是了解反应性是如何工作的!

文档中有关此主题的更多信息:https://mobx.js.org/understanding-reactivity.html