Reputation: 334
Good day!
I have an parent component:
@observer
class ToDos extends Component {
componentWillMount() {
this.state = new State();
this.onClearAllCompleted = this.onClearAllCompletedHandler.bind(this);
}
onClearAllCompletedHandler() {
this.state.clearAllCompleted();
}
render() {
const todos = this.state.todos;
return (
<Provider todos={todos}>
{this.props.children}
<ClearAllButton onClick={this.onClearAllCompleted} />
</Provider>
);
}
}
And state class for it:
class TodosState {
@observable todos = [
{ title: 'Sleep', completed: true },
{ title: 'Sleep more', completed: false },
{ title: 'Sleep more than before', completed: false }
];
@action
clearAllCompleted() {
this.todos = this.todos.filter(todo => !todo.completed);
}
}
When i try to clear all completed todos, it clears they with warning in browser console: MobX Provider: Provided store 'todos' has changed. Please avoid replacing stores as the change might not propagate to all children
.
After this nothing happens: i have old rendered html ;(
So, i think that childrens has observable object of todos that references to one object and after assign in state i have different ref. Childs dont know about this, and their observable doesn't changed at all. So, what i can do in this case?
Upvotes: 0
Views: 894
Reputation: 7365
The issue is in render
method - on each re-render you pass new todos
into Provider
component. Provider
component is tricky component which needs always the same props, but you pass different todos
array each time.
Corrected code: pass the whole state
object into Provider
(this.state
object is always the same in your example, just as Provider
wants)
render() {
return (
<Provider store={this.state}>
{this.props.children}
<ClearAllButton onClick={this.onClearAllCompleted} />
</Provider>
);
}
By the way I recommend you replace componentWillMount()
with constructor()
. Constructor is better place for store initialization. Especially in next versions of React (16.0+) componentWillMount()
might be called several times for the same instance before actual mount.
Upvotes: 2