问题描述
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
函数内部发生的事情:
-
let updated = this.persons.find((p) => p.id === id);
- 创建局部变量updated
并为其分配一些对象(人) -
const dummy_person = { first_name: 'foo',last_name: 'bar',id: 99 }
- 创建虚拟对象并将其分配给本地dummy_person
常量 -
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',id: 99 };
this.persons = this.persons.map(person => person.id === id ? dummy_person : person);
}
您可以做很多事情,这取决于您做什么。最重要的是了解反应性的工作原理!
文档中有关此主题的更多信息:https://mobx.js.org/understanding-reactivity.html