我在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";
答案 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}
/>