MobX:可观察的更改后,未观察到的组件不会重新渲染

时间:2018-10-14 21:38:51

标签: javascript reactjs react-native mobx mobx-react

我在React Native中有一个基本的MobX设置,但是在更新可观察对象后,我的组件不会重新渲染,而且我似乎无法弄清楚为什么。

本机 0.56.1 ;反应 16.4.1 ; mobx 4.5.0 ; mobx反应 5.2.8

商店

class AppStore {
  drawer = false;
  toggleDrawer = () => {
    this.drawer = !this.drawer;
  }
}
decorate(AppStore, {
  drawer: observable,
  toggleDrawer: action
});

const app = new AppStore();
export default app;

组件

class _AppLayout extends React.Component {
  constructor(props) {
    super(props);

    this.state = {
      drawerAnimation: new Animated.Value(0)
    };
  }

  UNSAFE_componentWillReceiveProps(nextProps) {
    console.log('will not get called');
    if (this.props.app.drawer !== nextProps.app.drawer) {
      Animated.timing(this.state.drawerAnimation, {
        toValue: nextProps.app.drawer === true ? 1 : 0,
        duration: 500
      }).start();
    }
  }

  render() {
    console.log("will only be called on first render");
    const translateX = this.state.drawerAnimation.interpolate({
      inputRange: [0, 1],
      outputRange: [0, -(width - 50)]
    });

    return (
      <Animated.View style={[styles.app, { transform: [{ translateX }] }]}>
        <View style={styles.appContent}>
          <RouterSwitch />
        </View>
        <View style={styles.appDrawer} />
      </Animated.View>
    );
  }
}
const AppLayout = inject("app")(observer(_AppLayout));

触发(来自不同组件)

<TouchableOpacity
  onPress={() => {
    app.toggleDrawer();
    // will reflect the new value
    console.log(app.drawer)
  }}
  style={styles.toggle}
/>

编辑: 经过一番调查后,没有触发任何重新提交,因为我没有在render()方法中使用存储,仅在componentWillReceiveProps中使用了存储。这对我来说似乎很奇怪?

当我在渲染器中使用存储时,即使只是分配一个变量,它也会开始工作:

const x = this.props.app.drawer === false ? "false" : "true";

2 个答案:

答案 0 :(得分:1)

根据mobx文档,

  

观察者函数/装饰器可用于将ReactJS组件转换为反应组件。它将组件的render函数包装在mobx.autorun中,以确保在组件渲染期间使用的所有数据都会在更改后强制重新渲染。可通过单独的mobx-react程序包获得。

因此,您需要使用观察者组件的内部this.props.app.drawer渲染函数来接收来自mobx的反应。

请参阅this link,了解有关mobx如何以及何时做出反应的更多详细信息。

答案 1 :(得分:0)

您需要在组件上使用observer中的mobx-react,并且最好使用装饰器。还要确保您在根组件上使用Provider

商店

class AppStore {
  @observable drawer = false;
  @action toggleDrawer = () => {
    this.drawer = !this.drawer;
    console.log(this.drawer)
  }
}

组件

const app = new AppStore();
export default app;

@observer 
class AppLayout extends React.Component {
  constructor(props) {
    super(props);

    this.state = {
      drawerAnimation: new Animated.Value(0)
    };
  }

  UNSAFE_componentWillReceiveProps(nextProps) {
    console.log('will not get called');
    if (this.props.app.drawer !== nextProps.app.drawer) {
      Animated.timing(this.state.drawerAnimation, {
        toValue: nextProps.app.drawer === true ? 1 : 0,
        duration: 500
      }).start();
    }
  }

  render() {
    console.log("will only be called on first render");
    const translateX = this.state.drawerAnimation.interpolate({
      inputRange: [0, 1],
      outputRange: [0, -(width - 50)]
    });

    return (
      <Provider app={app}>
        <Animated.View style={[styles.app, { transform: [{ translateX }] }]}>
          <View style={styles.appContent}>
            <RouterSwitch />
          </View>
          <View style={styles.appDrawer} />
        </Animated.View>
      </Provider>
    );
  }
}

触发

<TouchableOpacity
  onPress={() => {
    app.toggleDrawer();
    // will reflect the new value
    console.log(app.drawer)
  }}
  style={styles.toggle}
/>