1

Could you please help me in passing objects in a state array to the table using map method in react? I can able to push the object into the invoices array but I can't map into the table. Please suggest if any other method is possible.

Please neglect the below comments as I am going repeat the above context.

Could you please help me in passing objects in a state array to the table using map method in react? I can able to push the object into the invoices array but I can't map into the table. Please suggest if any other method is possible.

import React, { Component } from 'react';

class Form extends Component {
constructor(props) {
    super(props);
    this.state = {
        company: "",
        address: "",
        zip: "",
        date: "",
        description: "",
        unit: "",
        quantity: "",
        invoices: []
    };
}

handleChange = (e) => {
    e.preventDefault();
    this.setState({ [e.target.name]: e.target.value })
};

handleSubmit = (e) => {
    e.preventDefault();
    this.state.invoices.push({
        description: this.state.description,
        unit: this.state.unit,
        quantity: this.state.quantity
    });
    //console.log(this.state.invoices[].description);

};

render() {
    const hrStyle = {
        border: '5px solid rgb(23, 162, 184)'
    };

    const list = this.state.invoices.map((invoice, index) => {
        return (
            <tr key={index}>
                <td>{invoice[index].description}</td>
                <td>{invoice[index].unit}</td>
                <td>{invoice[index].quantity}</td>
                <td>{invoice[index].unit * invoice[index].quantity}</td>
            </tr>
        )
    });

    return (
        <React.Fragment>
            <div className='col-12 col-lg-6'>
                <div className="jumbotron">
                    <form>
                        <label><h4>Billed To: </h4></label><br />
                        <div className="form-group">
                            <label>Company Name</label>
                            <input onChange={this.handleChange} className="form-control" type="text" name="company" />
                        </div>
                        <div className="form-group">
                            <label>Address</label>
                            <input className="form-control" type="text" onChange={this.handleChange} name="address" />
                            <label>Zip Code</label>
                            <input className="form-control" type="number" onChange={this.handleChange} name="zip" /></div>
                        <div className="form-group">
                            <label>Date</label>
                            <input className="form-control" type="date" onChange={this.handleChange} name="date" />
                        </div>
                    </form>
                    <form onSubmit={this.handleSubmit}>
                        <label><h4>Invoice: </h4></label><br />
                        <div className="form-group">
                            <label>Description</label>
                            <input className="form-control" type="text" onChange={this.handleChange} name="description" />
                        </div>
                        <div className="form-group">
                            <label>Unit Price</label>
                            <input className="form-control" type="number" onChange={this.handleChange} name="unit" />
                            <label>Quantity</label>
                            <input className="form-control" type="number" onChange={this.handleChange} name="quantity" />
                        </div>
                        <button className="btn btn-primary btn-sm">Add Invoices</button>

                    </form>
                </div>
            </div>
            <div className="col-12 col-lg-6">
                <div className="container-fluid bg-info text-white">
                    <div className="row">
                        <div className="col text-left">
                            <p>Your Company Name</p>
                            <h2>Invoice</h2>
                        </div>
                        <div className="col text-right">
                            <p>22 Yusen St</p><br />
                            <p>Auburn</p><br />
                            <p>NSW</p>
                        </div>
                    </div>
                </div>
                <div className="container-fluid">
                    <div className="row">
                        <div className="col-4">
                            <p>{this.state.company}</p>
                            <p>{this.state.address}</p>
                            <p>{this.state.Zip}</p>
                        </div>
                        <div className="col-4">
                            <div>
                                <h5>Invoive number</h5>
                                <p>{Math.floor((Math.random() * 100) + 1)}</p>
                            </div>
                            <div>
                                <h5>Date</h5>
                                <p>{this.state.date}</p>
                            </div>
                        </div>
                        <div className="col-4">
                            <div>
                                <h5>Invoice Totals</h5>
                                <p>$2587.35</p>
                            </div>
                        </div>
                    </div>
                </div>
                <hr style={hrStyle} />
                <div className="Invoices">
                    <table className="table">
                        <thead>
                            <tr>
                                <th>Description</th>
                                <th>Unit Price</th>
                                <th>Quantity</th>
                                <th>Total</th>
                            </tr>
                        </thead>
                        <tbody>
                            {list}
                        </tbody>
                    </table>
                </div>
            </div>
        </React.Fragment>

    );
}
}

export default Form;
Mohamed Mubarak
  • 113
  • 2
  • 2
  • 6
  • Hey, have you looked at pre-made table components, you just need to pass an array of data to render the table. Some of my favorites are antd-table(https://ant.design/components/table/#components-table-demo-basic) or react-table (https://react-table.js.org/) – Shivam Gupta Oct 26 '18 at 13:47

2 Answers2

2

One possible issue that I can see is not properly setting state in handleSubmit. You should do something like this:

handleSubmit = (e) => {
    e.preventDefault();
    const copyStateInvoices = [...this.state.invoices]
    copyStateInvoices.push({
        description: this.state.description,
        unit: this.state.unit,
        quantity: this.state.quantity
    })
    this.setState({
      invoices: copyStateInvoices,
    })
    //console.log(this.state.invoices[].description);

};

Component's state is immutable and if you try to change the values in state it will happen but react will not respect that. Read more about these fundamentals on react main website.

Thanks

simbathesailor
  • 3,681
  • 2
  • 19
  • 30
0

Try with following changes.

Needs change in pushing objects to an array state

To push objects or values or numbers in react you should do something like below. The recommended approach to push values to an array in React is using prevState

   handleSubmit = (e) => {
       e.preventDefault();
       this.setState(prevState => ({
          invoices: [...prevState.invoices, {
          description: this.state.description,
          unit: this.state.unit,
          quantity: this.state.quantity
       }]
  }));
   };

And in .map you no need to do invoice[index] to get the value because you are doing .map on array so it gives you each object in loop so you can directly access invoice.unit directly and invoice[index].unit is not needed and not correct in loop

   const list = this.state.invoices.map((invoice, index) => {
    return (
        <tr key={index}>
            <td>{invoice.description}</td>
            <td>{invoice.unit}</td>
            <td>{invoice.quantity}</td>
            <td>{invoice.unit * invoice.quantity}</td>
        </tr>
    )
});
Hemadri Dasari
  • 32,666
  • 37
  • 119
  • 162