我有一个React 16.5.2组件,该组件将其部分状态传递给子组件,但是当父状态改变时,子组件不会被更新(子组件的componentWillReceiveProps不会被调用)。
以下是基本知识:
class ProductForm extends React.Component {
constructor(props){
super(props)
this.handlePropertiesFormChange.bind(this)
...
}
handlePropertiesFormChange(commodityProps) {
const comm = this.state.commodity
comm.properties = commodityProps
this.setState({
commodity: comm,
})
}
render() {
return(
<ProductProperties
commodity={ this.state.commodity }
parentEvtHandler={ this.handlePropertiesFormChange }
/>
)
}
}
class ProductProperties extends React.Component {
constructor(props) {
super(props)
this.state = { showDrugCatalog: false, synonyms: props.commodity.getSynonyms() || '' }
}
componentWillReceiveProps(nextProps) {
// this logging does not appear after calling this.props.parentEvtHandler()
// when ProductForm's parent CreateProduct is updated,
// this method is called and everything renders properly
console.log("==== cWRP in productProperties, nextProps = ", nextProps)
....
}
}
render() {
// numerous calls to various methods of this.props.commodity,
// which all work fine whenever this component is updated
}
}
在两个组件的初始呈现时,ProductProperty都会成功接收ProductForm的state.commodity。在ProductProperty中编辑输入字段时,组件将调用props.parentEvtHandler(代表ProductForm中更改状态的函数)。发生此调用时,ProductForm会正确更新其状态-调用其render()并将其对state.commodity进行引用,以表明状态已正确更新。
问题在于,state.commodity的新值未传递给ProductProperties。实际上,由于没有触发登录该组件的componentWillReceiveProps,因此似乎根本没有更新ProductProperties。
在更新ProductForm的父级CreateProduct时,道具正确地流向ProductProperties,调用componentWillReceiveProps,并且一切都正确呈现。
我尝试过的一件事: 由于仅对对象的属性进行了对state.commodity的更改,我认为React无法看到该对象已更改,因此尝试使用由Object.assign创建的全新的state.commodity克隆来更新状态。不能解决问题。
这个问题很奇怪,因为另一个父组件在没有发生此问题的情况下已经使用了ProductProperties组件一段时间。我看不到ProductForm和其他没有出现此问题的父组件之间的区别。 (最初,ProductForm的父级CreateProduct使用getDerivedStateFromProps管理其内部状态,但是即使我将其更改为使用componentWillReceiveProps,问题仍然存在。)
答案 0 :(得分:0)
我发现某种可以解决问题的方法,尽管我认为这不能解决根本原因。
当我更改ProductForm使其不再通过它的handlePropertiesFormChange的预绑定副本时,而是在每个render()绑定一个新副本时,问题就消失了。问题代码:
<ProductProperties
commodity={ this.state.commodity }
parentEvtHandler={ this.handlePropertiesFormChange }
/>
没有出现此问题的代码:
<ProductProperties
commodity={ this.state.commodity }
parentEvtHandler={ this.handlePropertiesFormChange.bind(this) }
/>
我认为重新绑定只是掩盖了核心问题-通过新绑定的函数,React认为有必要将新的props传递给ProductProperty,但它应该看到这种需求仅基于state.commodity的变化。这也解释了为什么使用ProductProperty的其他组件没有出现问题(它们重新绑定了功能)。