最近在写react时,需要在props被改变时更新一些东西,所以使用了componentWillReceiveProps
方法,但是却发现该方法总是在各种没有改变props的情况下被调用,觉得很奇怪,遂询问我导师(我导师超厉害的!),我导师说这个方法确实有可能在props不改变的情况下被调用,所以需要在方法里手动判断一下this.props和nextProps是否相同,不相同了才执行我的更新方法。于是我抽空阅读了一下官方的文档https://developmentarc.gitbooks.io/react-indepth/content/life_cycle/update/component_will_receive_props.html,研究了一下这个方法到底是怎么回事。下面先看一下componentDidMount()方法与componentWillReceiveProps()方法的对比。
componentDidMount()
在生命周期中只会被调用一次:
- 在最开始的render后被调用(在所有的子元素都已经被render之后,并且所有的子元素都已经被调用它们的
componentDidMount
s 之后)
- 组件在被卸载后的render(这确实是一个新的生命周期)
componentWillReceiveProps()在生命周期的第一次render后不会被调用,但是会在之后的每次render中被调用 = 当父组件再次传送props。
该方法当props
发生变化时执行,初始化render
时不执行,在这个回调函数里面,你可以根据属性的变化,通过调用this.setState()
来更新你的组件状态,旧的属性还是可以通过this.props
来获取,这里调用更新状态是安全的,并不会触发额外的render
调用。
componentWillReceiveProps: function(nextProps) {
this.setState({
likesIncreasing: nextProps.likeCount > this.props.likeCount
});
}
传递props
import React from 'react';
import Person './Person';
export default class Form extends React.Component {
constructor(props) {
super(props);
this.state = { name: '' } ;
this.handleChange = this.handleChange.bind(this);
}
handleChange(event) {
this.setState({ name: event.currentTarget.value });
}
render() {
return (
<div>
<input type="text" onChange={ this.handleChange } />
<Person name={ this.state.name } />
</div>
);
}
}
更新 State
Props may not change
this.setState({ data: [1,2,31);">3] });
<MyComponent data={ this.state.data } />
- 当旧的props和新的props实际上是相同的物理对象时(只更改了对象的内部值),由于引用是triple-equals-equal,所以进行相等性的检查并不能告诉我们该值是否已更改,唯一可能的解决方案是创建数据的深层拷贝,然后再进行深入比较。但对于大型数据结构(特别是具有周期的数据结构)而言,所花费的代价可能过于昂贵。
- props对象可能会包含 对函数的引用,这些函数可能会捕获闭包中的变量。 而React无法窥视这些闭包,因此React无法拷贝它们or验证相等性。
- props对象可能包含对父对象渲染过程中重新实例化的对象的引用(即不是triple-equals-equal),但在概念上相等(即相同的键和相同的值)。深度比较(代价昂贵)可以检测到这一点,除了函数,因为没有可靠的方法来比较两个函数以判断它们是否在语义上等价。
Skipping this method
// ...
handleChange(event) {
return (
<div>
<input type="text" onChange={ this.handleChange } />
<Person name={ this.state.name } />
</div>
);
}
// ...