反应孩子正在通过道具改变父母状态......我不清楚原因

Posted

技术标签:

【中文标题】反应孩子正在通过道具改变父母状态......我不清楚原因【英文标题】:React children are mutating parent state through props...I am unclear as to the cause 【发布时间】:2016-08-22 11:45:52 【问题描述】:

我有一个 React 组件,它将一个对象传递给一个包含要通过传递函数修改的输入字段的子元素。输入字段正在更改子元素的状态,但不知何故,在不调用传递的函数的情况下,props 对象正在被修改。

这是父类的渲染函数:

render: function() 
    const newTriggerClass = this.state.item.triggerID === ""
        ? " new-trigger"
        : "";
    return (
        <div className=newTriggerClass>
            <div className="triggers-detail">

                <section className="trigger-info group">
                    <TriggerInfoEntry
                    item=this.state.item
                    triggerState=this.state.editTriggerState
                    columnHeaders=this.props.columnHeaders
                    hideDetail=this.hideDetail
                    editAction=this.props.editAction
                    editToggle=this.editToggle
                    _onChange=this._onInfoChange
                    createAction=this.props.createAction
                    deleteAction=this.props.deleteAction/>
                </section>

                <section className="trigger-actions group">
                    <TriggerActionEntry
                    item=this.state.item
                    actionState=this.state.editActionState
                    editToggle=this.editToggle
                    editAction=this.editTriggerAction
                    actionIndex=this.state.selectedActionIndex/>
                </section>
            </div>
            <div className="modal-overlay" + newTriggerClass>
            </div>
        </div>
    );
,

TriggerActionEntry 将它自己的 state.item 设置为 props.item 的克隆。

propTypes: 
    item: React.PropTypes.object.isRequired,
    editAction: React.PropTypes.func.isRequired,
    editToggle: React.PropTypes.func.isRequired,
    actionState: React.PropTypes.bool
,

getInitialState: function() 
    return 
        item: assign(testy: true, this.props.item),
        actionIndex: 0,
        deleteState: false,
        editState: false
    ;
,

当我通过输入更改子组件 (state.item) 的状态时,父状态会更改!我不确定原因。我在网上阅读的任何内容都没有暗示这种行为。任何帮助表示赞赏。

更新: @garrettmaring 我用来更改状态的代码仅设计用于在 getInitialState 中设置为this.props.itemassign 的克隆的子状态,这是我的别名object-assign 这是Object.assign ponyfill .更改item 的表格实际上是多了一个孩子。这是TriggerActionEntry的渲染图

<div>
                    <TriggerActionForm
                    action=this.state.item.actions[this.state.actionIndex]
                    index=this.state.actionIndex
                    addNewAction=this.addNewAction
                    editTriggerAction=this.editTriggerAction
                    deleteTriggerAction=this.deleteTriggerAction
                    editState=this.state.editState
                    deleteState=this.props.actionState
                    toggleEdit=this.toggleEdit
                    activateEdit=this.activateEdit/>
 </div>

这里是孙子TriggerActionForm的_onChange函数

_onChange: function (e) 
    e.preventDefault();
    let newAction = assign(, this.state.action);
    const keyname = e.currentTarget.dataset.keyname;
    if (keyname === "minDelay") 
        newAction[keyname] = e.currentTarget.value;
     else 
        newAction.args[keyname] = e.currentTarget.value;
    
    this.setState(action: newAction);
    if (!this.props.editState) 
        this.props.activateEdit();
    
,

即使我卸载该组件,TriggerActionEntry state.item 也会被修改,并在再次安装组件时显示为修改状态...

更新 2:好的,问题是 Object.assignobject-assign 都没有深度克隆对象。经典!这些操作是嵌套在item 中的对象,而不是被克隆,而是创建了对嵌套对象的另一个引用。谢谢大家的帮助。

【问题讨论】:

嗯,你在getInitialState函数中试过Object.assign(, testy: true, this.props.item)吗?或者在传递之前创建this.state.item 的克隆。这似乎是一个参考问题。也就是说,即使你在getInitialState中使用了assign,子组件中的item仍然持有对父组件中state.item的引用。 @suntruth 向我们展示您在子元素上使用 setState 的代码。似乎您正在更改对象的属性,如果这是真的,它与父元素具有的对象引用相同,因此它也会更改。如果要为项目设置新状态,则应在使用setState 时完全创建一个新对象,不仅对项目使用assign,还对整个对象使用assign。 @garrettmaring,我在问题中添加了更多细节。感谢您的回复 我会尝试在 getInitialState 之外进行克隆,看看是否是问题所在。 【参考方案1】:

我目前正在做同样的事情。父级将数据作为道具传递给子级函数。 (我使用钩子而不是类)。子组件的目的是处理从父组件提供的数据并导出为 pdf 或 excel。想象一下数据作为一个包含多个对象数组的对象传入。每个子对象都有一个我想删除的 proj id 元素。数据传入的那一刻,我有这个 enter image description here

我使用从父级传入的数据设置状态。当我完成一些过程并删除 projid。当我尝试使用父函数中的任何元素进行访问时。整个事情都坏了。

【讨论】:

以上是关于反应孩子正在通过道具改变父母状态......我不清楚原因的主要内容,如果未能解决你的问题,请参考以下文章

通过孩子的状态 <Field> 组件更新父母道具

反应父母对孩子道具传递而不重新渲染

React,如何从父母那里访问孩子的状态?无需更新父母的状态

反应孩子与父母的沟通问题

将所有状态和道具传递给孩子们反应

在不改变状态、道具或父级的情况下反应子级渲染