【问题标题】:How to update object in Mobx observable array如何更新 Mobx 可观察数组中的对象
【发布时间】:2021-03-14 19:40:53
【问题描述】:

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
  }

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

【问题讨论】:

  • 当您编写updated = dummy_person 时,您只是用新值更新updated 引用。 MobX 在那个阶段没有参与。你可以尝试这样的事情:let updatedIndex = this.persons.findIndex((p) => p.id === id); this.persons.splice(updatedIndex, 1, dummy_person);

标签: javascript reactjs mobx mobx-react


【解决方案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

【讨论】:

  • 嗨,丹妮拉,感谢您的回复。我想我明白你说的。只有一个后续问题。您说“您只是在更新局部变量,而不是实际对象。” ...但是为什么我刚刚做updated.first_name = "FOO" 的第一种方法在它应该只是一个局部变量的情况下工作呢?!
  • 因为第一种方法实际上是在访问(“打点”)个人对象属性。基本上你是说“改变first_name 的东西updated 盒子持有”
猜你喜欢
  • 2020-12-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多