首页 > 解决方案 > 当渲染方法中没有使用 observable 时,如何让 MobX 更新组件?

问题描述

在从 Redux 切换到 MobX for React 之后,我开始非常喜欢 MobX。这真是太棒了。

MobX 有一个特定的行为,如果提供的 store observable 没有在渲染中使用,它不会更新组件。我认为通常这是一种非常棒的行为,它使组件仅在实际发生更改时才呈现。

但是......我确实遇到了一些我不想或不需要在渲染方法中使用 MobX observable 的情况,在这种情况下,我this.props.store的 MobX 商店不会得到更新。

在这种情况下,作为一种解决方法,我只是在 render 方法中引用 observable,但我认为这不是一个非常干净的方法,我想知道是否有更清洁的方法来做到这一点?

这个组件代码应该更多地解释我到底在问什么。它是一个基于我商店中的 MobX 可观察对象更改正文溢出样式的组件。

/*------------------------------------*\
  Imports
\*------------------------------------*/
import React from 'react';
import connectStore from 'script/connect-store';
import addClass from 'dom-helpers/class/addClass';
import removeClass from 'dom-helpers/class/removeClass';


/*------------------------------------*\
  Component
\*------------------------------------*/
class Component extends React.Component {

  constructor(props) {
    super(props);
    this.constructor.displayName = 'BodyClassSync';
  }

  componentDidMount() {
    this.checkAndUpdateMuiClass();
  }

  componentDidUpdate() {
    this.checkAndUpdateMuiClass();
  }

  checkAndUpdateMuiClass() {

    // This place is the only place I need latest MobX store... 
    if (this.props.store.muiOverlay) {
      addClass(window.document.body, 'mod-mui-overlay');
    }

    else {
      removeClass(window.document.body, 'mod-mui-overlay');
    }

  }


  render() {

    // This is my workaround so the componentDidUpdate will actually fire
    // (with latest and updated store)
    // when the 'muiOverlay' observable changes in the MobX store
    // Is there any cleaner/better way to do this?
    this.props.store.muiOverlay;

    // This component doesn't and shouldn't render anything
    return null;

  }



}



/*------------------------------------*\
  Export
\*------------------------------------*/
const ComponentWithStore = connectStore(Component);
export default ComponentWithStore;

(注意:我不使用@decorators,我在 connectStore 函数中使用 ES5 语法连接商店。如果解决方案也出现在 ES5 中,那就太棒了。)

标签: javascriptreactjsmobxmobx-react

解决方案


您可以使用自动运行并在componentDidMount其中配置侦听器,componentWillUnmount这样您就不必在渲染方法中引用它。

class Component extends React.Component {
  constructor(props) {
    super(props);
    this.constructor.displayName = 'BodyClassSync';
  }

  componentDidMount() {
    this.dispose = autorun(() => {
      const { muiOverlay } = this.props.store;

      if (muiOverlay) {
        addClass(window.document.body, 'mod-mui-overlay');
      } else {
        removeClass(window.document.body, 'mod-mui-overlay');
      }
    });
  }

  componentWillUnmount() {
    this.dispose();
  }

  render() {
    return null;
  }
}

由于您实际上并没有在此组件中做任何事情,因此您也可以将其autorun直接放在您的商店中。


推荐阅读