如何在React中传递值而不是引用?

时间:2017-06-02 17:12:02

标签: javascript reactjs ecmascript-6

我有以下文件:LookupPage.jsx和AccountDetails.jsx。

在LookUp中

this.updateCustomer = (customer) => {

    if(JSON.stringify(customer.address) !== JSON.stringify(this.state.activeAccount.customer.address)) {
            console.log('address changed');
            customer.update_address = true;
            customer.address.source = 'user';
        }
    return fetch(
        `${API_ENDPOINT}/customer/${customer.id}/`,
        {
            method: 'PATCH',
            headers: {
                'Authorization': 'Token ' + this.props.session_token,
                    'Content-Type': 'application/json',
            },
            body: JSON.stringify(customer),
        }
    ).then(restJSONResponseToPromise).then(responseJSON => {
        if(responseJSON.results){
            console.log('update customers client side.')
        }
    }, clearSessionIfInvalidToken(this.props.clearSession));
};

<AccountsDetailModal
    show={this.state.showAccountDetail}
    close={this.toggleAccountDetail}
    customer={this.state.activeAccount.customer}
    updateCustomer={this.updateCustomer}
/>

一边是AccountDetails

this.onChangeAddress = (e) => {
    const customer = {...this.state.customer};
    const address = customer.address;
    address[e.target.name] = e.target.value;
    customer.address = address;
    this.setState({customer, errors: {
        ...this.state.errors,
        [e.target.name]: [],
    }});
};

this.saveCustomer = () => {
    this.setState({postDisable: true});
    const errors = this.getFormErrors();
    const hasErrors = !every(errors, (item) => !item.length);
    if(!hasErrors){
        this.props.updateCustomer(this.state.customer);
    } else {
        sweetAlert('Error!', 'Form is invalid.', 'error');
    }
    this.setState({postDisable: false});
};

this.componentDidMount = () => {
    this.setState({customer: this.props.customer});
}

当我更新客户地址时,它正在更新活动帐户地址,因此它似乎是通过引用传递的。我想要发生的只是更新客户地址,如果地址已更改/与原始地址不同。如何修改我的代码来执行此操作?

2 个答案:

答案 0 :(得分:0)

您可以通过传递JS中的任何对象(无论您是否使用React):

JSON.parse(JSON.stringify(myObject))

作为参数而不是对象本身。

基本上这只是克隆对象并传递它的副本,因此您可以在不影响原始的情况下操作所需的副本。

请注意,如果对象包含函数,则它将不起作用,它只会复制属性。 (在你的例子中,这应该没问题。)

答案 1 :(得分:0)

我要把我的两分钱放在这里:

首先,这并不是React特有的,而是更多与JS相关的问题。

其次,在反应方面,设置道具反对内部状态被认为是一种不好的做法。鉴于您的特定情况,确实没有必要这样做。我指的是

this.setState({customer: this.props.customer});

因此,遇到问题,您遇到引用问题的原因是因为您在代码中的某些点上改变了传入对象的原始内容。例如,如果我看一下:

this.updateCustomer = (customer) => {

    if(JSON.stringify(customer.address) !== JSON.stringify(this.state.activeAccount.customer.address)) {
            console.log('address changed');
            customer.update_address = true;
            customer.address.source = 'user';
        }
};

您正在改变参数对象的原始道具,这些道具很可能在组件的其他方法中传递。所以,要克服这个问题,你可以做到:

const updatedCustomer = Object.assign({}, customer, {
  update_address: true
});

您可以在API调用中传递updatedCustomerObject.assign()不会对传入的对象执行操作,但会返回一个新对象,因此您可以确保在应用中的任何位置都不会改变原始对象。

注意: Object.assign适用于普通对象,而不是嵌套对象。因此,如果您想要实现类似于嵌套对象属性的类似内容,则可以使用lodash merge