假设我们对父组件有两个子节点C1和C2进行了以下设置:
Example: container for C1 and C2, with a state called data
-C1: input, updates state in Example through handler passed as propdisplay, shows state from Example
-C2: display, shows state from Example
这是代码和codepen:
class Example extends React.Component {
constructor (props) {
super(props)
this.state = { data: 'test' }
}
onUpdate (data) { this.setState({ data }) }
render () {
return (
<div>
<C1 onUpdate={this.onUpdate.bind(this)}/>
<C2 data={this.state.data}/>
</div>
)
}
}
class C1 extends React.Component {
constructor(props) {
super(props);
this.onUpdate = this.props.onUpdate;
}
render () {
return (
<div>
<input type='text' ref='myInput'/>
<input type='button' onClick={this.update.bind(this)} value='Update C2'/>
</div>
)
}
update () {
//this.props.onUpdate(this.refs.myInput.getDOMNode().value);
this.onUpdate(this.refs.myInput.getDOMNode().value);
}
}
class C2 extends React.Component {
constructor(props) {
super(props);
this.data = this.props.data;
}
render () {
return <div>{this.props.data}</div>
//return <div>{this.data}</div>
}
}
/*
* Render the above component into the div#app
*/
React.render(<Example />, document.getElementById('app'));
请注意,在C2的构造函数中,我们引用了this.props.data
。如果我们将该变量设置为像this.data = this.props.data
这样的类属性,即使我们单击更新按钮并且示例的this.state.data已更改,React也无法更新C1。我已经注释掉了有效的行,它直接引用了this.props.data。
我的第一个想法是,这必须是React中的非法语法。然而,使用C1进一步测试表明,如果传入的props是函数而不是状态,则没有问题(请参阅C1的update
函数下的代码来确认我在说什么)。
为什么这不适用于作为道具传入的状态,但适用于作为道具传入的函数?我假设Example看到C1已经改变data
状态,并且因此调用C2的重新渲染,使用this.data
来确定接下来要呈现的内容。
答案 0 :(得分:3)
因为constructor
只被调用一次而不是每次都获得新的状态或道具所以你的类变量引用最初传递的props而不是新的,因为它不会再次重新运行构造函数。见constructor
React组件的构造函数在挂载之前被调用
因此,一旦安装完毕,它就不会被再次呼叫。另一方面,功能,特别是纯函数,可以正常工作,因为你没有修改函数本身或其中的任何值。
如果您想根据道具更改更新类变量,可能需要检查shouldComponentUpdate或componentWillReceiveProps
例如,在您的C2
组件中修复它,请使用:
componentWillReceiveProps(nextProps) {
this.data = this.nextProps.data
}
但我觉得这样做很多,this.props
大部分时间都可以正常工作。