mobx 反应观察者组件在更新后不调用渲染
mobx react observer component isn't calling render after update
要求是:
Toggle to open the rows component
Highlight the selected row with a background color of cyan
但是,当我单击切换按钮时,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;
编辑 根据建议,我已将商店的创建提取到组件外部。
更新:您可以尝试使用 @action.bound
装饰器,并在构造函数中完全跳过 bind(this)
。我的猜测是手动绑定搞乱了绑定(没有双关语意)。
The action decorator / function follows the normal rules for binding in javascript. However, Mobx 3 introduces action.bound to automatically bind actions to the targeted object. Note that unlike action, (@)action.bound does not take a name parameter, so the name will always be based on the property name to which the action is bound.
您的商店未被观察到,因为它是在内部 render()
中创建的。您需要创建商店并将其通过 props
或 MobX 的 Provider.
传递给您的组件
Provider is a component that can pass stores (or other stuff) using React's context mechanism to child components. This is useful if you have things that you don't want to pass through multiple layers of components explicitly.
inject can be used to pick up those stores. It is a higher order component that takes a list of strings and makes those stores available to the wrapped component.
试试这个。
// 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;
要求是:
Toggle to open the rows component
Highlight the selected row with a background color of cyan
但是,当我单击切换按钮时,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;
编辑 根据建议,我已将商店的创建提取到组件外部。
更新:您可以尝试使用 @action.bound
装饰器,并在构造函数中完全跳过 bind(this)
。我的猜测是手动绑定搞乱了绑定(没有双关语意)。
The action decorator / function follows the normal rules for binding in javascript. However, Mobx 3 introduces action.bound to automatically bind actions to the targeted object. Note that unlike action, (@)action.bound does not take a name parameter, so the name will always be based on the property name to which the action is bound.
您的商店未被观察到,因为它是在内部 render()
中创建的。您需要创建商店并将其通过 props
或 MobX 的 Provider.
Provider is a component that can pass stores (or other stuff) using React's context mechanism to child components. This is useful if you have things that you don't want to pass through multiple layers of components explicitly.
inject can be used to pick up those stores. It is a higher order component that takes a list of strings and makes those stores available to the wrapped component.
试试这个。
// 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;