[英]ReactJS mobx - does not update observable array
If you have an observable
list in your store:如果您的商店中有一个observable
列表:
@obserable public Claimslist: IClaim[] = [];
where IClaim
is an interface, claims
is an array of IClaim
objects其中IClaim
是一个接口, claims
是一个IClaim
对象数组
IClaim
contains a varaible in its object called moveOutDate
Each claim object has id
variable. IClaim
在其对象中包含一个名为moveOutDate
变量。每个声明对象都有id
变量。
And now you want to update or get that variable by the claim
id现在您想通过claim
ID 更新或获取该变量
So you have 2 functions:所以你有两个功能:
Get得到
/**
* 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;
}
Set放
/**
* 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();
}
}
Okey, but now when you use getMoveOutDateById
at first in your render
it works and renders the date, but once you call setMoveOutDate
onUpdate
of the date component, the render won't update, but the store will update and you can only see changes if you refresh the page. getMoveOutDateById
,但是现在当您首先在render
使用getMoveOutDateById
时,它会起作用并渲染日期,但是一旦您调用日期组件的setMoveOutDate
onUpdate
,渲染将不会更新,但存储将更新,您只能看到更改你刷新页面。
Now I managed to solve it, by doing:现在我设法通过执行以下操作来解决它:
this.Claimslist = this.Claimslist.slice();
and adding an hidden input of Claimslist:并添加 Claimslist 的隐藏输入:
const {Claimslist} = this.props.claimsStore;
and和
<input type="hidden" value={Claimslist} />
Why does it happen, if the whole object is obserable
and is wrapped with @action
why doesn't it change without using slice()
and having an hidden input?为什么会发生,如果整个对象是可obserable
并且用@action
包裹,为什么不使用slice()
和隐藏输入它不会改变?
Mobx observable
only observes shallow values. Mobx observable
只观察浅层值。 Meaning lets say I have @observable claims[]
then claims[0] = something
will trigger an update but claims[0].foo = bar
will not (docs) .意思是说我有@observable claims[]
然后@observable claims[]
claims[0] = something
会触发更新,但@observable claims[]
claims[0].foo = bar
不会(docs) 。 To fix this you need to make foo
also observable by adding @observable foo
on claim
object.要解决此问题,您需要通过在claim
对象上添加@observable foo
来使foo
也可观察。
Consider the following example.考虑以下示例。 Notice the difference between Claim1
and Claim2
.注意之间的差异Claim1
和Claim2
。 The components are exactly same yet ClaimView2
will update and ClaimView1
will not.组件完全相同,但ClaimView2
会更新而ClaimView1
不会。 Demo 演示
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")
);
Here's a demo for the solution I gave in the comments这是我在评论中给出的解决方案的演示
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")
);
It is not exactly the same, missing @observable, it will be the same if:它不完全相同,缺少@observable,如果:
class Claim1 {
@observable moveOutDate: Date;
...
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.