在 mobx 观察者更改后反应不重新渲染
React not rerendering after mobx observer change
页面加载后,我看到 "hi2"
当我点击按钮时,没有任何反应。我也试过 setUser
。
我怀疑我只是在自己编辑道具,不知何故没有触发 observable?
查看它在全新 rails/react 环境中无法正常工作的示例代码:https://github.com/bufordtaylor/mobxtest
- 克隆
- 捆绑包
- rails s
- (在另一个进程中)./bin/webpack-dev-server --host 127.0.0.1
- 导航到 localhost:3000
======================
更新:
我已将其简化为基本形式,消除了可能的导入错误、提供程序错误或构造函数错误。
在这里
import React from 'react'
import ReactDOM from 'react-dom'
import { observable, action, computed } from 'mobx';
import { Provider, inject, observer } from 'mobx-react';
class UserStore {
@action setUser(val) {
console.log(val);
this.user = val;
}
@observable user = "default";
}
const userStore = new UserStore();
@observer
class Hello extends React.Component {
render() {
return (
<div>
hi2 {this.props.userStore.user}
<button onClick={this.props.userStore.setUser.bind(this,"fwefwe")}>faew</button>
</div>
)
}
}
document.addEventListener('DOMContentLoaded', () => {
ReactDOM.render(
<Hello userStore={userStore} />,
document.getElementById('app'),
)
})
<button onClick={this.props.userStore.setUser.bind(this,"fwefwe")}>faew</button>
小心。您正在绑定 this
。 This
在本例中是 Hello 组件的实例。现在 setUser 函数中的 this
指向 Hello Component。所以setUser会在Hello组件中设置一个属性用户
@action setUser(val) {
console.log(val);
this.user = val; // This this now points to the Hello Component.
}
要理解我的意思,您可以在 setUser 方法上设置断点,然后检查变量 this。您会看到它指向 Hello 组件而不是您的商店实例。
改为执行以下操作:
<button onClick={() => { this.props.userStore.setUser("fwefwe"); }}>faew</button>
我在这里创建了一个在用户存储上调用 setUser 的 lambda。
因为我在这里使用的是lambda,所以this.props.userStore
中的this
指向Hello Component。
您的代码看起来不错。我认为您偶然发现了文档 How to (not) use decorators 部分中讨论的问题。重要的是 transform-decorators-legacy
在 babel 插件列表中排在第一位。
我的问题是包装组件的顺序,因为我使用的是 Material UI 框架。
错误:
export inject('store')(observer(withStyles(styles)(MyComponent)));
正确:
export withStyles(styles)(inject('store')(observer(MyComponent)));
所以,MobX 和 React Material UI.[=12= 的顺序很重要]
我遇到了类似的问题,我在渲染方法中使用了箭头函数:
render = (): React.ReactNode
正确的应该是:
render(): React.ReactNode
仍然不确定为什么第一个案例会混淆 mobx。
对于到达这里的任何人,请确保您不是像我这样的白痴,并且您没有忘记在 class 组件之前添加 @observer
装饰器。
(或店内@observable
装修师傅)
天哪,浪费了一整天
如果你使用最新版本的mobx,以及babel 7.12版本
将此添加到您的构造函数
makeObservable(this)
我确定发生这种情况的原因有多种。
在我的例子中,我没有使用装饰器。我只是在我的 mobx 状态对象的构造函数中使用了 makeAutoObservable(this)
。我的组件没有在状态更改时重新呈现的原因是因为我没有将默认值应用到状态 属性.
我有一个 属性 定义如下:
showModalForIssue: IssueTreeNode;
我有一个 observer
组件正在使用这个 属性 但没有重新渲染它的值。
经过多次讨论后,我最终通过简单地在其定义中应用默认值(将其设置为 null
)来修复它,如下所示:
showModalForIssue: IssueTreeNode = null;
这一定与 makeAutoObservable(this)
的工作原理有关。
在我的例子中,虽然 运行 是旧版本的 mobx (4.3),但问题来自一个组件,该组件呈现另一个组件并将 lambda 传递给 returns 一个节点
@observer
class Parent extends Component {
@observable
value = "Initial";
renderSub() {
return <Text>{this.value}</Text>
}
render() {
return <Child primary={() => this.renderSub()} onPress={() => (this.value = "Other")} />;
}
}
class Child extens Component {
render() {
return this.props.primary();
}
}
这会中断。解决方法是直接传递节点:
class Parent extends Component {
render() {
return <Child primary={this.renderSub()} />;
}
}
这可能是因为 lambda 在不同的组件中进行渲染,因此不在父组件的更改跟踪范围内,另一个可能的修复方法可能是将子组件也设为 @observer ,但我更喜欢我的修复方法,所以我没有尝试
页面加载后,我看到 "hi2"
当我点击按钮时,没有任何反应。我也试过 setUser
。
我怀疑我只是在自己编辑道具,不知何故没有触发 observable?
查看它在全新 rails/react 环境中无法正常工作的示例代码:https://github.com/bufordtaylor/mobxtest
- 克隆
- 捆绑包
- rails s
- (在另一个进程中)./bin/webpack-dev-server --host 127.0.0.1
- 导航到 localhost:3000
======================
更新:
我已将其简化为基本形式,消除了可能的导入错误、提供程序错误或构造函数错误。
在这里
import React from 'react'
import ReactDOM from 'react-dom'
import { observable, action, computed } from 'mobx';
import { Provider, inject, observer } from 'mobx-react';
class UserStore {
@action setUser(val) {
console.log(val);
this.user = val;
}
@observable user = "default";
}
const userStore = new UserStore();
@observer
class Hello extends React.Component {
render() {
return (
<div>
hi2 {this.props.userStore.user}
<button onClick={this.props.userStore.setUser.bind(this,"fwefwe")}>faew</button>
</div>
)
}
}
document.addEventListener('DOMContentLoaded', () => {
ReactDOM.render(
<Hello userStore={userStore} />,
document.getElementById('app'),
)
})
<button onClick={this.props.userStore.setUser.bind(this,"fwefwe")}>faew</button>
小心。您正在绑定 this
。 This
在本例中是 Hello 组件的实例。现在 setUser 函数中的 this
指向 Hello Component。所以setUser会在Hello组件中设置一个属性用户
@action setUser(val) {
console.log(val);
this.user = val; // This this now points to the Hello Component.
}
要理解我的意思,您可以在 setUser 方法上设置断点,然后检查变量 this。您会看到它指向 Hello 组件而不是您的商店实例。
改为执行以下操作:
<button onClick={() => { this.props.userStore.setUser("fwefwe"); }}>faew</button>
我在这里创建了一个在用户存储上调用 setUser 的 lambda。
因为我在这里使用的是lambda,所以this.props.userStore
中的this
指向Hello Component。
您的代码看起来不错。我认为您偶然发现了文档 How to (not) use decorators 部分中讨论的问题。重要的是 transform-decorators-legacy
在 babel 插件列表中排在第一位。
我的问题是包装组件的顺序,因为我使用的是 Material UI 框架。
错误:
export inject('store')(observer(withStyles(styles)(MyComponent)));
正确:
export withStyles(styles)(inject('store')(observer(MyComponent)));
所以,MobX 和 React Material UI.[=12= 的顺序很重要]
我遇到了类似的问题,我在渲染方法中使用了箭头函数:
render = (): React.ReactNode
正确的应该是:
render(): React.ReactNode
仍然不确定为什么第一个案例会混淆 mobx。
对于到达这里的任何人,请确保您不是像我这样的白痴,并且您没有忘记在 class 组件之前添加 @observer
装饰器。
(或店内@observable
装修师傅)
天哪,浪费了一整天
如果你使用最新版本的mobx,以及babel 7.12版本 将此添加到您的构造函数
makeObservable(this)
我确定发生这种情况的原因有多种。
在我的例子中,我没有使用装饰器。我只是在我的 mobx 状态对象的构造函数中使用了 makeAutoObservable(this)
。我的组件没有在状态更改时重新呈现的原因是因为我没有将默认值应用到状态 属性.
我有一个 属性 定义如下:
showModalForIssue: IssueTreeNode;
我有一个 observer
组件正在使用这个 属性 但没有重新渲染它的值。
经过多次讨论后,我最终通过简单地在其定义中应用默认值(将其设置为 null
)来修复它,如下所示:
showModalForIssue: IssueTreeNode = null;
这一定与 makeAutoObservable(this)
的工作原理有关。
在我的例子中,虽然 运行 是旧版本的 mobx (4.3),但问题来自一个组件,该组件呈现另一个组件并将 lambda 传递给 returns 一个节点
@observer
class Parent extends Component {
@observable
value = "Initial";
renderSub() {
return <Text>{this.value}</Text>
}
render() {
return <Child primary={() => this.renderSub()} onPress={() => (this.value = "Other")} />;
}
}
class Child extens Component {
render() {
return this.props.primary();
}
}
这会中断。解决方法是直接传递节点:
class Parent extends Component {
render() {
return <Child primary={this.renderSub()} />;
}
}
这可能是因为 lambda 在不同的组件中进行渲染,因此不在父组件的更改跟踪范围内,另一个可能的修复方法可能是将子组件也设为 @observer ,但我更喜欢我的修复方法,所以我没有尝试