reactjs通过道具将对象数组从父状态传递给子对象

时间:2019-02-09 12:12:57

标签: javascript reactjs

我的代码如下:

class Parent extends React.Component {

    constructor(props) {
        super(props);
        this.state = {arr: [{id: 1, val: 11}, {id: 2, val: 22}]}
    }

    render(){
        return (
            <div>
                <Child Arr = {this.state.arr} />
            </div>
        )
    }
}

class Child extends React.Component {

    constructor(props) {
        super(props);
        this.changeVal = this.changeVal.bind(this)
        this.arr = props.Arr
    }

    changeVal(){
        this.arr[0].val *= 2
    }

    render(){
        return (
            <div>
                <input type='button' value='change val' onClick={this.changeVal} />
            </div>
        )
    }
}

我意识到在按下按钮后,孩子的道具和父母的状态发生了变化。 enter image description here enter image description here 我以为,当我将道具分配给局部变量时:

this.arr = props.Arr

我可以更改此局部变量,而不会影响其来源的道具或状态。

将传递的prop分配给局部变量时,复制传递的prop是正确的解决方案(下面的代码),还是使用更复杂的状态通常是个坏主意-例如对象等的数组?

class Child extends React.Component {

    constructor(props) {
        super(props);
        this.changeVal = this.changeVal.bind(this)
        //this.arr = props.Arr
        this.arr = this.copyArrayOfObjects(props.Arr)
    }

    copyArrayOfObjects(arrToCopy){
        if(arrToCopy == null){
            return null
        }

        let arrToRet = []
        for(let i=0; i<arrToCopy.length; i++){
            let obj = {...arrToCopy[i]}
            arrToRet.push(obj)
        }  

        return arrToRet
    }

    changeVal(){
        this.arr[0].val *= 2
    }

    render(){
        return (
            <div>
                <input type='button' value='change val' onClick={this.changeVal} />
            </div>
        )
    }
}

2 个答案:

答案 0 :(得分:1)

this.arr = [...props.Arr]

以上操作并没有真正解决问题,我也不满意对推荐的reactjs(文档)替代解决方案的满意。从一开始,ReactJS就声称状态是私有的,道具是只读的,数据流是一个方向。当它的组件传递给组件时,突然之间,当带有数组的对象作为道具传递时,它的行为很奇怪。这是Reactjs中的设计缺陷。

我使用了lodash(npm i --save lodash),然后在从父级传递到子级的同时克隆了该对象。它彻底解决了我的问题,应用程序开始按预期运行。

答案 1 :(得分:0)

对象作为参考传递,而不是作为值传递。因此,通过更改child中的值,您最终将在该引用处更改值。

this.arr = props.Arr

将此行更改为

this.arr = [...props.Arr]

如果您的组件完全依赖道具并且您不需要本地状态,那么这值得一读fully controlled component