Reactjs React:更新处于状态的对象数组的正确方法

Reactjs React:更新处于状态的对象数组的正确方法,reactjs,react-bootstrap,Reactjs,React Bootstrap,我是一名自学成才的专业网络开发人员。我创建了这个表作为更大表单的一部分。 该表在表单组件内被调用 <ProductList products={this.state.products} onChange={products => this.sendUpdate('products', products)} /> 这一部分在我所有的表单更新中都非常有效。但现在我正试图弄清楚如何处理表内的更新。每个产品都是表中的一行,如下所示: <tbody>

我是一名自学成才的专业网络开发人员。我创建了这个表作为更大表单的一部分。 该表在表单组件内被调用

<ProductList
    products={this.state.products}
    onChange={products => this.sendUpdate('products', products)}
/>
这一部分在我所有的表单更新中都非常有效。但现在我正试图弄清楚如何处理表内的更新。每个产品都是表中的一行,如下所示:

<tbody>
    {this.props.products.map((product, i) =>
        <Product key={i} data={product} products={this}/>
    )}
</tbody>

{this.props.products.map((product,i)=>
)}
当我输入一个输入时,更新状态的正确方法是什么

<FormControl
    value={this.props.data.species}
    onClick={e => this.updateProduct('species', e.target.value)}
/>
this.updateProduct('species',e.target.value)}
/>
ProductList的完整代码

import React from "react";
import {Button, Table, FormControl} from "react-bootstrap";

class Product extends React.Component {

    updateField(...props){
        this.props.products.updateProduct(this.data, ...props)
    }

    render() {
        return (
            <tr>
                <td>
                    <FormControl
                        value={this.props.data.species}
                        onClick={e => this.updateProduct('species', e.target.value)}
                    />
                </td>
                <td><FormControl/></td>
                <td><FormControl/></td>
                <td><FormControl/></td>
                <td><FormControl/></td>
                <td><FormControl/></td>
                <td><FormControl type="number"/></td>
                <td><Button bsStyle="danger" onClick={() => this.props.products.deleteProduct(this.props.data)}>X</Button></td>
            </tr>
        );
    }
}

export default class ProductList extends React.Component {
    constructor(...props) {
        super(...props);
    }

    addProduct() {
        let products = this.props.products.concat([{timestamp: Date.now()}]);
        this.props.onChange(products);
    }

    updateProduct(product, field, newValue) {
        this.props.products;
        // ???
    }

    deleteProduct(product) {
        let products = this.props.products.filter(p => {
            return p !== product
        });
        this.props.onChange(products);
    }

    render() {
        return (
            <Table responsive>
                <thead>
                <tr>
                    <th>Species</th>
                    <th>Dried</th>
                    <th>Cut</th>
                    <th>Dimensions Green</th>
                    <th>Dimensions Dry</th>
                    <th>Color</th>
                    <th>Quantity</th>
                    <th className="text-right">
                        <Button bsStyle="success" bsSize="xsmall" onClick={() => this.addProduct()}>Add</Button>
                    </th>
                </tr>
                </thead>
                <tbody>
                {this.props.products.map(product => <Product key={product.timestamp} data={product} products={this}/>)}
                </tbody>
            </Table>
        );
    }
}
从“React”导入React;
从“react bootstrap”导入{Button,Table,FormControl};
类产品扩展了React.Component{
updateField(…道具){
this.props.products.updateProduct(this.data,…props)
}
render(){
返回(
this.updateProduct('species',e.target.value)}
/>
this.props.products.deleteProduct(this.props.data)}>X
);
}
}
导出默认类ProductList扩展React.Component{
构造函数(…道具){
超级(…道具);
}
addProduct(){
让products=this.props.products.concat([{timestamp:Date.now()}]);
此.props.onChange(产品);
}
updateProduct(产品、字段、新值){
这是道具产品;
// ???
}
删除产品(产品){
让products=this.props.products.filter(p=>{
返回p!==产品
});
此.props.onChange(产品);
}
render(){
返回(
种
干燥的
削减
绿色尺寸
尺寸干燥
颜色
量
this.addProduct()}>Add
{this.props.products.map(product=>)}
);
}
}
这就是我根据公认的答案得出的结论:

import React from "react";
import {Button, Table, FormControl} from "react-bootstrap";


export default class ProductList extends React.Component {
    constructor(...props) {
        super(...props);
    }

    addProduct() {
        let products = this.props.products.concat([{}]);
        this.props.onChange(products);
    }

    updateProduct(product, field, newValue) {
        const products = this.props.products.map(p => {
            return p === product ? {...p, [field]: newValue} : p;
        });
        this.props.onChange(products);
    }

    deleteProduct(product) {
        let products = this.props.products.filter(p => {
            return p !== product
        });
        this.props.onChange(products);
    }

    render() {
        return (
            <Table responsive striped>
                <thead>
                <tr>
                    <th>Species</th>
                    <th>Dried</th>
                    <th>Cut</th>
                    <th>Dimensions Green</th>
                    <th>Dimensions Dry</th>
                    <th>Color</th>
                    <th>Quantity</th>
                    <th className="text-right">
                        <Button bsStyle="success" bsSize="xsmall" onClick={() => this.addProduct()}>Add</Button>
                    </th>
                </tr>
                </thead>
                <tbody>
                {this.props.products.map((product, i) => this.renderRow(i, product, this))}
                </tbody>
            </Table>
        );
    }

    renderRow(i, product) {
        return (
            <tr key={i}>
                <td>
                    <FormControl
                        value={product.species || ''}
                        onChange={e => this.updateProduct(product, 'species', e.target.value)}
                    />
                </td>
                <td>
                    <FormControl
                        value={product.dried || ''}
                        onChange={e => this.updateProduct(product, 'dried', e.target.value)}
                    />
                </td>
                <td>
                    <FormControl
                        value={product.cut || ''}
                        onChange={e => this.updateProduct(product, 'cut', e.target.value)}
                    />
                </td>
                <td>
                    <FormControl
                        value={product.dimensionsGreen || ''}
                        onChange={e => this.updateProduct(product, 'dimensionsGreen', e.target.value)}
                    />
                </td>
                <td>
                    <FormControl
                        value={product.dimensionsDry || ''}
                        onChange={e => this.updateProduct(product, 'dimensionsDry', e.target.value)}
                    />
                </td>
                <td>
                    <FormControl
                        value={product.color || ''}
                        onChange={e => this.updateProduct(product, 'color', e.target.value)}
                    />
                </td>
                <td>
                    <FormControl
                        type="number"
                        value={product.quantity || 0}
                        onChange={e => this.updateProduct(product, 'quantity', e.target.value)}
                    />
                </td>
                <td><Button bsStyle="danger" onClick={() => this.deleteProduct(product)}>X</Button></td>
            </tr>
        );
    }
}
从“React”导入React;
从“react bootstrap”导入{Button,Table,FormControl};
导出默认类ProductList扩展React.Component{
构造函数(…道具){
超级(…道具);
}
addProduct(){
让products=this.props.products.concat([{}]);
此.props.onChange(产品);
}
updateProduct(产品、字段、新值){
const products=this.props.products.map(p=>{
返回p==产品?{…p,[字段]:newValue}:p;
});
此.props.onChange(产品);
}
删除产品(产品){
让products=this.props.products.filter(p=>{
返回p!==产品
});
此.props.onChange(产品);
}
render(){
返回(
种
干燥的
削减
绿色尺寸
尺寸干燥
颜色
量
this.addProduct()}>Add
{this.props.products.map((product,i)=>this.renderRow(i,product,this))}
);
}
renderRow(一、产品){
返回(
this.updateProduct(产品'species',e.target.value)}
/>
this.updateProduct(产品'dry',e.target.value)}
/>
this.updateProduct(产品'cut',e.target.value)}
/>
this.updateProduct(产品'dimensionsGreen',e.target.value)}
/>
this.updateProduct(product'dimensionsDry',e.target.value)}
/>
this.updateProduct(product'color',e.target.value)}
/>
this.updateProduct(产品'quantity',e.target.value)}
/>
this.deleteProduct(product)}>X
);
}
}

产品列表的
呈现()中,将数组映射更改为类似以下内容:

{this.props.products.map((product, index) => <Product key={product.timestamp} data={product} index={index} products={this}/>)}
最后,将
ProductsList
updateProduct()
更改为:

updateField(...props){
    this.props.products.updateProduct(this.props.index, ...props)
}
updateProduct(index, field, newValue) {
    const products = this.props.products.map((product, productIndex)) => {
        if (index === productIndex) {
            return {
                ...product,
                [field]: newValue
            };
        }
        return product;
    })
    this.props.onChange(products);
}

另外,
Product
render中有一点输入错误。
FormControl
onClick
应为
onClick={e=>this.updateField('species',e.target.value)}

使用。。。填充新对象上的值,但不使用新对象执行任何操作。我错过了在不编辑道具的情况下替换产品阵列上的产品的步骤。除了复制整个产品阵列,然后拼接到我们的新对象中,还有其他捷径吗?这并不像我在最后一点上想象的那么糟糕,谢谢!
updateProduct(index, field, newValue) {
    const products = this.props.products.map((product, productIndex)) => {
        if (index === productIndex) {
            return {
                ...product,
                [field]: newValue
            };
        }
        return product;
    })
    this.props.onChange(products);
}