2017-02-23 17 views
1

私は自分自身を教えるプロのWeb開発者です。私はこのテーブルをより大きなフォームの一部として作成しました。 animated gif showing me clicking buttons to add and remove rows テーブルは、フォーム部品の内側に呼び出されReact:状態のオブジェクトの配列を更新する適切な方法

<ProductList 
    products={this.state.products} 
    onChange={products => this.sendUpdate('products', products)} 
/> 

this.sendUpdate:

sendUpdate(field, value) { 
    this.setState({[field]: value}); 
    socket.emit('updateItem', this.state.id, {[field]: value}); 
} 

その部分はすべて私のフォームの更新ですべての作業に最適です。今はテーブル内の更新をどのように処理するかを考えようとしています。各製品は、次のように呼び出された表の行です:

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

私は入力の一つに入力したときに状態を更新する適切な方法は何ですか?

<FormControl 
    value={this.props.data.species} 
    onClick={e => 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> 
     ); 
    } 
} 

のための完全なコードをこれは私が受け入れ答えに基づいになってしまったものです:あなたProductsList年代render()

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> 
     ); 
    } 
} 

答えて

2

に配列マップを変更次のようなもの:

{this.props.products.map((product, index) => <Product key={product.timestamp} data={product} index={index} products={this}/>)} 
あなたの Product

次に年代はにupdateField()を変更します。

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

そして最後に、変更ProductsList」へのupdateProduct()

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に若干の誤植があります。 FormControlonClickonClick={e => this.updateField('species', e.target.value)}となります。

+0

クールトリックを使用して新しいオブジェクトに値を入力しますが、新しいオブジェクトでは何もしません。私はプロダクトを編集せずにプロダクトアレイ上の製品を置き換える段階がありません。製品配列全体をコピーして新しいオブジェクトにスプライスする以外のショートカットはありますか? – FreakinaBox

+0

申し訳ありませんが、その部分を逃した!私は答えを編集 – Lucas

+0

私はその最後のビット、感謝のために想像していたほど悪くはなかった! – FreakinaBox

関連する問題