mobx反应观察者组件在更新后不会调用渲染

时间:2017-09-14 11:00:44

标签: javascript reactjs mobx mobx-react

要求是:

  

切换以打开行组件

     

使用青色

的背景颜色突出显示所选行

但是,当我点击切换按钮时,App组件不会被重新渲染:(

// App.js
import React, { Component } from 'react';
import {observable, action } from 'mobx';
import {observer} from 'mobx-react';

@observer class Rows extends Component {
  rows() {
    let { store } = this.props;
    var rows = [];
    for (var i = 4; i > 0; i--) {
      rows.push(
        <div
          style={i == store.selectedRow ? { backgroundColor: "cyan" } : null }
          onClick={store.selectRow.bind(this, i)}>
          { i }
        </div>
      )
    }
    return rows;
  }
  render() {
    return (<div>{this.rows()}</div>);
  }
}

class Store {
  constructor(props) {
    this.selectRow = this.selectRow.bind(this)
    this.toggleSelector = this.toggleSelector.bind(this)
  }
  @observable showSelector = false;
  @observable selectedRow = 4;
  @action selectRow(n) {
    this.selectedVersion = n;
  }
  @action toggleSelector() {
    this.showSelector = !this.showSelector;
  }
}

//edit here
const store = new Store();

@observer class App extends Component {
  render() {
    return (
      <div className="App">
        <button onClick={store.toggleSelector}>Toggle Selector</button>
        { store.showSelector ? <Rows store={store}/> : null }
      </div>
    );
  }
}

export default App;

编辑根据建议,我已经在组件外部提取了商店的创建。

2 个答案:

答案 0 :(得分:2)

更新:您可以尝试使用@action.bound装饰器,并在构造函数中完全跳过bind(this)。我的猜测是手动绑定会破坏绑定(没有双关语)。

请参阅action.bound

  

动作装饰器/函数遵循javascript中绑定的常规规则。但是,Mobx 3引入了action.bound以自动将操作绑定到目标对象。请注意,与action不同,(@)action.bound不接受name参数,因此名称将始终基于绑定操作的属性名称。

您的商店未被观察,因为它是 render()内创建的。您需要创建商店并通过props或MobX的Provider将其传递给您的组件。

  

Provider是一个可以使用React的上下文机制将存储(或其他东西)传递给子组件的组件。如果你有一些不想明确地通过多层组件的东西,那么这很有用。

     

注入可以用来拿起那些商店。它是一个更高阶的组件,它接受一个字符串列表并使这些存储可用于包装组件。

答案 1 :(得分:0)

试试这个。

// App.js
import React, { Component } from 'react';
import {observable, action } from 'mobx';
import {observer} from 'mobx-react';

@observer class Rows extends Component {
  rows() {
    let { store } = this.props;
    var rows = [];
    for (var i = 4; i > 0; i--) {
      rows.push(
        <div
          style={i == store.selectedRow ? { backgroundColor: "cyan" } : null }
          onClick={store.selectRow.bind(this, i)}>
          { i }
        </div>
      )
    }
    return rows;
  }
  render() {
    return (<div>{this.rows()}</div>);
  }
}

class Store {
  constructor(props) {
    this.selectRow = this.selectRow.bind(this)
    this.toggleSelector = this.toggleSelector.bind(this)
  }
  @observable showSelector = false;
  @observable selectedRow = 4;
  @action selectRow(n) {
    this.selectedVersion = n;
  }
  @action toggleSelector() {
    this.toggleSelector = !this.showSelector;
  }
}

// defined outside
const store = new Store();

@observer class App extends Component {
  render() {
    return (
      <div className="App">
        <button onClick={store.toggleSelector}>Toggle Selector</button>
        { store.showSelector ? <Rows store={store}/> : null }
      </div>
    );
  }
}

export default App;