In MobX how can I set new values to a whole observable array without re-setting every value?
First thought would be:
let arr = observable([]);
autorun(() => {
console.log('my array changed!');
});
arr = ['foo', 'bar'];
But that would not fire the autorun
, I would just erased my observable array
and replaced it with a new value/array.
So, what is the correct way to do this?
My solution to this was to use another variable with a setter , and inside the setter function change the observable array index by index , replacing, adding and deleting indexes. Like this:
( jsFiddle here )
const {observable, computed, extendObservable} = mobx;
const {observer} = mobxReact;
const {Component} = React;
const {render} = ReactDOM
const {autorun} = mobx
class Store {
@observable entries = [1,2,3,4,5];
set rows(arr) {
// add new values
for (let i = 0, l = arr.length; i < l; i++) {
this.entries[i] = arr[i];
}
// remove rest of entries
let diff = this.entries.length - arr.length;
if (diff > 0) {
while (diff > 0) {
this.entries.pop();
diff--;
}
}
}
}
const store = new Store();
@observer
class App extends Component {
updateRows(){
return this.props.entries.map(
(row, i) => <p key={i}>{row}</p>
);
}
render() {
const rows = this.updateRows();
return <div>{rows}</div>;
}
}
setTimeout(() => {
store.rows = ['foo', 'bar'];
document.body.innerHTML += 'Timeout fired...';
}, 1000);
render(
<App entries={store.entries} />,
document.getElementById('mount')
);
Is this the correct way?
or is there a way to just use the same variable to re-assign a value to the whole array?
TLDR; use store.entries.replace(['foo', 'bar']);
I found a method .replace()
that will replace the content of the whole array and trigger the render. I found it after a suggestion about the clear()
method and from there looking more carefully into the docs
.replace(newItems);
Replaces all existing entries in the array with new ones.
The code would then look like this:
( jsFiddle )
const {observable, autorun} = mobx;
class Store {
@observable arr = [1,2,3,4,5];
}
const store = new Store();
autorun(() => {
console.log('my array changed!', store.arr.slice());
});
setTimeout(() => {
store.arr.replace(['foo', 'bar']);
}, 1000);
The whole code would be:
( jsFiddle )
const {observable, computed, extendObservable} = mobx;
const {observer} = mobxReact;
const {Component} = React;
const {render} = ReactDOM
const {autorun} = mobx
class Store {
@observable entries = [1,2,3,4,5];
}
const store = new Store();
@observer
class App extends Component {
updateRows(){
return this.props.entries.map(
(row, i) => <p key={i}>{row}</p>
);
}
render() {
const rows = this.updateRows();
return <div>{rows}</div>;
}
}
setTimeout(() => {
store.entries.replace(['foo', 'bar']);
}, 1000);
render(
<App entries={store.entries} />,
document.getElementById('mount')
);
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.