Если в вашем магазине есть список observable:
@obserable public Claimslist: IClaim[] = [];
где IClaim — интерфейс, claims — массив IClaim объектов
IClaim содержит переменную в своем объекте с именем moveOutDate
Каждый объект претензии имеет id переменную.
И теперь вы хотите обновить или получить эту переменную по claim id
Итак, у вас есть 2 функции:
Получать
/**
* Gets the moveOutDate of a claim by claim ID
*/
@action getMoveOutDateById = (id: string) => {
// Get the claim by id
const claim = this.Claimslist.find((element: IClaim) => element.id === sessionStorage.getItem('claim-id'));
if (claim) {
if (!claim.moveOutDate) {
return undefined;
}
return moment(new Date(claim.moveOutDate)).toDate();
}
return undefined;
}
Задавать
/**
* Sets moveOutDate in claim by claim ID
*/
@action public setMoveOutDate = (id: string, date: Date) => {
const claim = this.Claimslist.find((element: IClaim) => element.id === id);
if (claim) {
claim.moveOutDate = date.toString();
}
}
Хорошо, но теперь, когда вы сначала используете getMoveOutDateById в своем render, он работает и отображает дату, но как только вы вызываете setMoveOutDateonUpdate компонента даты, рендеринг не будет обновляться, но хранилище будет обновляться, и вы сможете увидеть изменения, только если вы обновляете страницу.
Теперь мне удалось решить эту проблему, выполнив:
this.Claimslist = this.Claimslist.slice();
и добавление скрытого ввода Claimslist:
const {Claimslist} = this.props.claimsStore;
а также
<input type = "hidden" value = {Claimslist} />
Почему это происходит, если весь объект obserable и обернут @action, почему он не меняется без использования slice() и наличия скрытого ввода?



![Безумие обратных вызовов в javascript [JS]](https://i.imgur.com/WsjO6zJb.png)


Mobx observable наблюдает только мелкие значения. Это означает, что у меня есть @observable claims[], тогда claims[0] = something вызовет обновление, но claims[0].foo = bar не будет (документы). Чтобы исправить это, вам нужно сделать foo также наблюдаемым, добавив @observable foo к claim объекту.
Рассмотрим следующий пример. Обратите внимание на разницу между Claim1 и Claim2. Компоненты точно такие же, но ClaimView2 будут обновляться, а ClaimView1 — нет. Демо
import React from "react";
import { render } from "react-dom";
import { observable, action } from "mobx";
import { observer } from "mobx-react";
class Claim1 {
moveOutDate: Date;
constructor() {
this.moveOutDate = new Date();
}
}
@observer
class ClaimsView1 extends React.Component {
@observable claims: Claim1[] = [
new Claim1(),
new Claim1()
];
@action.bound
updateClaims(){
this.claims.forEach(claim => {
claim.moveOutDate = new Date();
})
}
render() {
return <div>
<pre>
{"ClaimsView1 = \n" + JSON.stringify(this.claims, null, " ")}
</pre>
<button onClick = {this.updateClaims}> Update </button>
</div>
}
}
class Claim2 {
@observable moveOutDate: Date;
constructor() {
this.moveOutDate = new Date();
}
}
@observer
class ClaimsView2 extends React.Component {
@observable claims: Claim2[] = [
new Claim2(),
new Claim2()
];
@action.bound
updateClaims(){
this.claims.forEach(claim => {
claim.moveOutDate = new Date();
})
}
render() {
return <div>
<pre>
{"ClaimsView2 = \n" + JSON.stringify(this.claims, null, " ")}
</pre>
<button onClick = {this.updateClaims}> Update </button>
</div>
}
}
render(
<>
<ClaimsView1 />
<ClaimsView2 />
</>,
document.getElementById("root")
);
Вот демо для решения, которое я дал в комментариях.
import React from "react";
import { render } from "react-dom";
import { observable, action } from "mobx";
import { observer } from "mobx-react";
interface IClaim {
moveOutDate: Date;
}
@observer
class ClaimsView extends React.Component<{claims: IClaim[]}> {
@observable claims: IClaim[] = this.props.claims.map(claim => observable(claim))
updateClaims = () => {
this.claims.forEach(claim => {
claim.moveOutDate = new Date();
})
}
render() {
return <div>
<pre>
{"claims = \n" + JSON.stringify(this.claims, null, " ")}
</pre>
<button onClick = {this.updateClaims}> Update </button>
</div>
}
}
render(
<ClaimsView claims = {[
{ moveOutDate: new Date() },
{ moveOutDate: new Date() }
]} />,
document.getElementById("root")
);
@Ben Вы по-прежнему можете сделать каждое свойство наблюдаемым, передав объект интерфейса IClaim наблюдаемому декоратору/функции, а затем поместив его в массив. документы
@Ben и ofc, если у вас уже есть заполненный массив, вы можете сопоставить его с помощью функции observable и переназначить массив.
@Ben Я обновил ответ демонстрацией реализации решения в случае интерфейсов. Пожалуйста, проверьте это.
Привет спасибо! Но вы должны понимать, что я использую интерфейс с необязательными свойствами, например, переменная?: строка; так что вы не можете сделать это, я думаю
@ Бен, почему ты думаешь, что не можешь этого сделать? замените interface IClaim { moveOutDate: Date } на interface IClaim { moveOutDate: Date, foo?: string } и все равно будет работать. Также Добро пожаловать!
но можете ли вы сделать это и для необязательных переменных?
@ Бен Да. Вот демо. Я думаю, это то, что вы хотели, верно?
Давайте продолжить обсуждение в чате.
Это не совсем то же самое, отсутствует @observable, это будет то же самое, если:
class Claim1 {
@observable moveOutDate: Date;
...
Но IClaim — это интерфейс, и вы не можете сделать это в интерфейсе?