在没有第三方库的情况下在React中克隆嵌套状态属性?

时间:2018-11-26 14:24:42

标签: reactjs

目前,我正在和一些用户编辑器一起玩。 当然,我碰到过反应原理:“永远不要直接改变this.state”

假设下面的代码片段是一个简单的用户编辑器(未显示:未将用户对象作为按钮保存单击时的json推送到Web服务):

import React, { Component } from 'react';

class App extends Component {
    constructor(props) {
        super(props);
        this.onChange = this.onChange.bind(this);
        this.state = {
            user: {
                name: 'me',
                parents: {
                    mother: 'mary',
                    father: 'john',
                },
                hobbies: [
                    {
                        name: 'soccer',
                        location: 'home'
                    },
                    {
                        name: 'tennis',
                        location: 'home'
                    }
                ]
            }
        };
    }

    onChange(e) {
        let user = this.state.user; // 1 - no copy - reference
        //let user = {...this.state.user}; // 2 - shallow copy
        //let user = JSON.parse(JSON.stringify(this.state.user)); // 3 - deep copy

        switch (e.target.dataset.ptype) {
            case 'me':
                user.name = e.target.value;
                break;
            case 'mother':
                user.parents.mother = e.target.value;
                break;
            case 'father':
                user.parents.father = e.target.value;
                break;
            case 'hobby':
                user.hobbies[1].name = e.target.value;
                break;
            default:
                break;
        }

        this.setState({
            user: user
        });
    }

    render() {
        return (
            <div>
                <div><input data-ptype='me' onChange={this.onChange} value={this.state.user.name}/>{this.state.user.name}</div>
                <div><input data-ptype='mother' onChange={this.onChange} value={this.state.user.parents.mother}/>{this.state.user.parents.mother}</div>
                <div><input data-ptype='father' onChange={this.onChange} value={this.state.user.parents.father}/>{this.state.user.parents.father}</div>
                <div><input data-ptype='hobby' onChange={this.onChange} value={this.state.user.hobbies[1].name}/>{this.state.user.hobbies[1].name}</div>
                <div><pre>{JSON.stringify(this.state.user, null, 2)}</pre></div>
            </div>
        )
    }
}

export default App;

在onChange方法中,我尝试了三种不同的方法来更新当前用户对象:

  1. 参考
  2. 传播算子
  3. JSON.stringify

每种方法都能按预期工作。

在这种情况下,不同方法的缺点是什么?

当然,如果我仅通过引用更新用户对象,则setState的空调用也将反映更改。

setState如何处理/评估更新的状态对象以进行渲染吗?

br,苏西

1 个答案:

答案 0 :(得分:0)

实际上没有一种理想的方式来处理嵌套状态,要么有一个通用函数来处理对象的所有更新,要么编写很多单独的函数来处理应如何更新每个值。每个人都有其优点和缺点。

您的问题询问如何最好地克隆对象。这确实是一个单独的问题(answered here),但我建议您使用object spread语法,如下所示:

const user = {
  name: 'me',
  parents: {
    mother: 'mary',
    father: 'john',
  },
  hobbies: [{
      name: 'soccer',
      location: 'home'
    },
    {
      name: 'tennis',
      location: 'home'
    }
  ]
};

const addUserHobby = (user, newHobby) => ({
  ...user,
  hobbies: [
    ...user.hobbies,
    newHobby 
  ]
})

const updatedUser = addUserHobby(user, {
  name: 'hockey',
  location: 'home'
})

console.dir(updatedUser)