MobX:分配后重新渲染

MobX: rerender after assign

美好的一天!

我有一个父组件:

@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>
    );
  }
}

并声明class:

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);
  }
}

当我尝试清除所有已完成的待办事项时,它会在浏览器控制台中清除它们并发出警告:MobX Provider: Provided store 'todos' has changed. Please avoid replacing stores as the change might not propagate to all children

在这之后什么都没有发生:我已经渲染旧 html ;(

所以,我认为 childrens 有可观察的 todos 对象,它引用一个对象,在状态分配后我有不同的引用。 Childs 不知道这一点,他们的 observable 根本没有改变。那么,在这种情况下我能做什么?

问题出在 render 方法中 - 在每次重新渲染时,您将新的 todos 传递到 Provider 组件中。 Provider 组件是一个棘手的组件,它总是需要相同的道具,但你每次都传递不同的 todos 数组。

更正代码:将整个 state 对象传递给 Providerthis.state 对象在您的示例中始终相同,正如 Provider 所希望的那样)

render() {

    return (
      <Provider store={this.state}>
        {this.props.children}
        <ClearAllButton onClick={this.onClearAllCompleted} />
      </Provider>
    );
}

顺便说一下,我建议您将 componentWillMount() 替换为 constructor()。构造函数是商店初始化的更好地方。特别是在下一版本的 React (16.0+) 中,componentWillMount() 可能会在实际挂载之前为同一个实例调用多次。