【问题标题】:React component does not pass changed state to childReact 组件不会将更改的状态传递给子级
【发布时间】:2019-03-18 21:06:03
【问题描述】:

我有一个 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

    }


}

在两个组件的初始渲染中,ProductProperties 成功接收到 ProductForm 的 state.commodity。在 ProductProperties 中编辑输入字段时,组件会调用 props.parentEvtHandler(它表示 ProductForm 中更改状态的函数)。当这个调用发生时,ProductForm 正确地更新了它的状态——它的 render() 被调用并且它对 state.commodity 的引用表明状态被正确地更新了。

问题是,state.commodity 的新值没有传递给 ProductProperties。事实上,它似乎根本没有更新 ProductProperties,因为没有触发登录该组件的 componentWillReceiveProps。

当 ProductForm 的父 CreateProduct 更新时,props 正确地流向 ProductProperties,componentWillReceiveProps 被调用,一切都正确呈现。

我尝试过的一件事: 由于对 state.commodity 的更改仅对对象的属性进行,我认为 React 未能看到该对象已更改,因此尝试使用使用 Object.assign 创建的 state.commodity 的全新克隆来更新状态,但这没有解决问题。

这个问题很奇怪,因为 ProductProperties 组件已经被另一个父组件使用了一段时间,而没有出现这个问题。我发现 ProductForm 和其他没有出现此问题的父组件之间没有区别。 (原本 ProductForm 的父 CreateProduct 是用 getDerivedStateFromProps 管理其内部状态,但即使我将其更改为使用 componentWillReceiveProps,问题仍然存在。

【问题讨论】:

  • 代码和解释看起来很有说服力。你为什么不把你的问题写成codesandbox,让我们看看一个完整的、可复制的代码环境
  • 您能否分享一下 ProductForm 组件的预初始化状态,否则很难向您推荐可能的解决方案。如果可以共享两个组件代码就更好了
  • 谢谢,我已经添加了更多细节——我认为关键是 ProductProperty 渲染在调用时总是可以正常工作——问题是它并不总是在其父状态更改时调用。如果没有进一步的想法,我可以考虑在沙箱中获取一些工作代码。

标签: reactjs


【解决方案1】:

我发现了一些可以解决问题的方法,尽管我认为它不能解决根本原因。

当我更改 ProductForm 以使其不再传递它的 handlePropertiesFormChange 的预绑定副本,而是在每个 render() 绑定一个新副本时,问题就消失了。问题代码:

<ProductProperties
     commodity={ this.state.commodity }
     parentEvtHandler={ this.handlePropertiesFormChange }
/>

没有出现此问题的代码:

<ProductProperties
     commodity={ this.state.commodity }
     parentEvtHandler={ this.handlePropertiesFormChange.bind(this) }
/>

我认为重新绑定只是掩盖了核心问题——对于一个新绑定的函数,React 认为需要将新的 props 传递给 ProductProperties,但它应该看到这种需要仅基于 state.commodity 的变化。这也解释了为什么使用 ProductProperties 的其他组件没有出现问题(它们重新绑定了函数)。

【讨论】:

    猜你喜欢
    • 2019-01-20
    • 2022-01-18
    • 2019-11-21
    • 2020-09-09
    • 2022-07-15
    • 1970-01-01
    • 2019-08-09
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多