Detect update in observable prop

装载自:https://stackoverflow.com/questions/41736558/detect-update-in-observable-prop

Ask Question

up vote1down votefavorite

1

I have a component that has an observable as property:

class Store {
   @observable color = "red" 
}

const store = new Store(); 

@observer
class MyComponent extends React.Component {  
  componentWillReceiveProps(nextProps) {
    // Not called!
    console.log("Component will receive props", nextProps.store.color)
  }
  componentDidMount() {
    console.log("Component did mount", this.props.store.color)  
  }
  changeColor = () => {
    this.props.store.color = (this.props.store.color==="red")? "blue":"red";
  };
  render() {
    return <div>
        color: {this.props.store.color}  
        <button onClick={this.changeColor}>Change color</button>   
    </div>
  }
};

ReactDOM.render(<MyComponent store={store} />, document.body)

My problem is that componentWillReceiveProps is never called when the observed variable is changed (by clicking on the button), nor is componentDidReceiveProps or shouldComponentUpdate. However I can see in the rendered code that the color is indeed changed in the store.

reactjs observable mobx mobx-react

shareimprove this question

edited Jan 21 '17 at 19:00

asked Jan 19 '17 at 7:55

Christopher Chiche

11.4k74385

add a comment

2 Answers

activeoldestvotes

up vote4down vote

tl;dr: use componentWillUpdate and componentDidUpdate


The object Store passed as a prop never changes, even when its content changes. The trick of using @observable is that it will trigger the update in the component without changing the props. So using lifecycle functions such as shouldComponentUpdatecomponentWillReceiveProps and componentDidReceiveProps won't work with since they are triggered when either the component's props or state changes. The mobx doc explains it well in the shouldComponentUpdate section.

So, to catch an update in an observable, we must go a bit deeper in the lifecycle stack and use componentWillUpdate and componentDidUpdate.

So, the code should look like this:

@observer
class MyComponent extends React.Component {  
  componentWillReceiveProps(nextProps) {
    // Not called! 
    console.log("Component will receive props", nextProps.store.color)
  }
  componentWillUpdate(nextProps) {
    console.log("Component will update", nextProps.store.color)
  }
  componentDidMount() {
    console.log("Component did mount", this.props.store.color)  
  }
  changeColor = () => {
    this.props.store.color = (this.props.store.color==="red")? "blue":"red";
  };
  render() {
    return <div>
        color: {this.props.store.color}  
        <button onClick={this.changeColor}>Change color</button>   
    </div>
  }
};

JS Bin: http://jsbin.com/voqugezaya/edit?js,console,output

Under the cover, mobx-react uses the forceUpdate function to trigger the component to re-render without necessarily changing the objects in its props (only their content changes).

Also, there is a new function introduced by mobx, which is quite helpful for debugging: componentWillReact.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值