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

时间:2021-03-14 19:40:53

标签: javascript reactjs mobx mobx-react

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
  }

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

1 个答案:

答案 0 :(得分:1)

正如@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