Mobx Observable 不会导致观察者组件更新
Mobx Obervable Not Causing Observer Component To Update
要求是:
when user changes input in DayView component, the number of shifts in that day instance is changed to the input value (i.e. 4 in input means day.shifts.length == 4)
when day.shifts changes, then DayView.renderShifts causes N rows to be rendered
但是,更改输入值有效,但是 DayView.render 仅调用一次。 day.shifts 改变后应该再次调用。
我错过了什么?
这是我的观察者组件:
//App.js
import React from 'react';
import store from './ShiftStore';
import { observer } from 'mobx-react';
import { toJS } from 'mobx';
@observer class ShiftList extends React.Component {
render() {
return (
<div>
{ store.days.map(
(day, idx) => <DayView day={ day } key={ idx } />
) }
</div>
);
}
}
@observer class DayView extends React.Component {
renderShifts(day) {
var rows = [];
toJS(day.shifts).forEach(function(s) {
rows.push(<div>Shift Row</div>)
})
return rows;
}
render() {
const day = this.props.day;
return (
<div>
<input
type="number"
onChange={(e) => day.resizeShifts(e.target.value)}/>
{this.renderShifts(day)}
</div>
);
}
}
class App extends React.Component {
render() {
return (
<div className="App">
<ShiftList/>
</div>
);
}
}
export default App;
这是 mobx 方面:
//ShiftStore.js
import React from 'react';
import {observable, computed, action, toJS } from 'mobx';
class Shift {
@observable startTime = 10;
@observable endTime = 9;
@computed get duration() {
let { startTime, endTime } = this;
return endTime - startTime;
}
}
class Day {
@observable shifts = [];
@action resizeShifts(n) {
if (n < 0 || n % 1 !== 0) return;
let { shifts, _resize } = this;
let shiftArr = toJS(shifts);
_resize(shiftArr, n, new Shift());
shifts = shiftArr;
}
_resize(arr, newSize, defaultValue) {
while(newSize > arr.length)
arr.push(defaultValue);
arr.length = newSize;
}
}
class ShiftStore {
constructor(props) {
this.addDay = this.addDay.bind(this);
}
@observable days = [new Day()];
addDay() { this.days.push(new Day()); }
}
const shiftStore = new ShiftStore();
export default shiftStore;
您永远不会为 shifts
分配一个新数组。使用 replace 这样您就不会覆盖对可观察数组的引用:
@action resizeShifts(n) {
if (n < 0 || n % 1 !== 0) return;
let { shifts, _resize } = this;
let shiftArr = toJS(shifts);
_resize(shiftArr, n, new Shift());
this.shifts.replace(shiftArr);
}
要求是:
when user changes input in DayView component, the number of shifts in that day instance is changed to the input value (i.e. 4 in input means day.shifts.length == 4)
when day.shifts changes, then DayView.renderShifts causes N rows to be rendered
但是,更改输入值有效,但是 DayView.render 仅调用一次。 day.shifts 改变后应该再次调用。
我错过了什么?
这是我的观察者组件:
//App.js
import React from 'react';
import store from './ShiftStore';
import { observer } from 'mobx-react';
import { toJS } from 'mobx';
@observer class ShiftList extends React.Component {
render() {
return (
<div>
{ store.days.map(
(day, idx) => <DayView day={ day } key={ idx } />
) }
</div>
);
}
}
@observer class DayView extends React.Component {
renderShifts(day) {
var rows = [];
toJS(day.shifts).forEach(function(s) {
rows.push(<div>Shift Row</div>)
})
return rows;
}
render() {
const day = this.props.day;
return (
<div>
<input
type="number"
onChange={(e) => day.resizeShifts(e.target.value)}/>
{this.renderShifts(day)}
</div>
);
}
}
class App extends React.Component {
render() {
return (
<div className="App">
<ShiftList/>
</div>
);
}
}
export default App;
这是 mobx 方面:
//ShiftStore.js
import React from 'react';
import {observable, computed, action, toJS } from 'mobx';
class Shift {
@observable startTime = 10;
@observable endTime = 9;
@computed get duration() {
let { startTime, endTime } = this;
return endTime - startTime;
}
}
class Day {
@observable shifts = [];
@action resizeShifts(n) {
if (n < 0 || n % 1 !== 0) return;
let { shifts, _resize } = this;
let shiftArr = toJS(shifts);
_resize(shiftArr, n, new Shift());
shifts = shiftArr;
}
_resize(arr, newSize, defaultValue) {
while(newSize > arr.length)
arr.push(defaultValue);
arr.length = newSize;
}
}
class ShiftStore {
constructor(props) {
this.addDay = this.addDay.bind(this);
}
@observable days = [new Day()];
addDay() { this.days.push(new Day()); }
}
const shiftStore = new ShiftStore();
export default shiftStore;
您永远不会为 shifts
分配一个新数组。使用 replace 这样您就不会覆盖对可观察数组的引用:
@action resizeShifts(n) {
if (n < 0 || n % 1 !== 0) return;
let { shifts, _resize } = this;
let shiftArr = toJS(shifts);
_resize(shiftArr, n, new Shift());
this.shifts.replace(shiftArr);
}