After Button Clicked, Unable to Edit the Data - reactjs

I have a form, After filling the Details and clicking on Submit Button, It will redirect to the next page, There I Have One Edit button to edit the fields. But Edit functionality is working as Excepted.
Can Anyone help me in this?? Thanks in Advance
import React, { Component } from 'react';
import axios from "axios";
import {withRouter} from 'react-router';
class App extends Component {
constructor(props) {
super(props)
this.state = {
data:[],
objEdit:obj
}
}
handleInput(e){
this.setState({
objEdit:{...this.state.objEdit, [e.target.name] : e.target.value}
})
}
updateUser = () =>{
console.log(this.state.objEdit)
const objEdit = {...this.state.objEdit, id: null};
axios.post("http://localhost:3000/data/", objEdit).then(()=>{
this.props.history.push('/Form')
}).catch((error)=>{
console.log("Error Occured")
})
}
render() {
return (
<div>
<div className="col-sm-4">
<form>
<div className="form-group">
<label htmlFor="fname">First Name</label>
<input type="text" className="form-control" name="fname" placeholder="Enter First Name" value={this.state.objEdit.fname} onChange={(e)=>{this.handleInput(e)}}/>
</div>
<div className="form-group">
<label htmlFor="lname">Last Name</label>
<input type="text" className="form-control" name="lname" placeholder="Enter First Name" value={this.state.objEdit.lname} onChange={(e)=>{this.handleInput(e)}}/>
</div>
<div className="form-group">
<label htmlFor="tel">Tel</label>
<input type="text" className="form-control" name="tel" placeholder="Tel" value={this.state.objEdit.tel} onChange={(e)=>{this.handleInput(e)}}/>
</div>
<div className="form-group">
<label htmlFor="address">Address</label>
<input type="text" className="form-control" name="address" placeholder="Enter First Name" value={this.state.objEdit.address} onChange={(e)=>{this.handleInput(e)}}/>
</div>
<div className="form-group">
<label htmlFor="fname">City</label>
<input type="text" className="form-control" name="city" placeholder="Enter First Name" value={this.state.objEdit.city} onChange={(e)=>{this.handleInput(e)}}/>
</div>
<div className="form-group">
<label htmlFor="state">State</label>
<input type="text" className="form-control" name="state" placeholder="Enter First Name" value={this.state.objEdit.state} onChange={(e)=>{this.handleInput(e)}}/>
</div>
<div className="form-group">
<label htmlFor="zip">Zip</label>
<input type="text" className="form-control" name="zip" placeholder="Enter First Name" value={this.state.objEdit.zip} onChange={(e)=>{this.handleInput(e)}}/>
</div>
<button type="button" className="btn btn-primary" onClick={this.updateUser}>Submit</button>
</form>
</div>
</div>
)
}
}
export default withRouter(App);
let obj={
fname:"",
lname:"",
tel:"",
address:"",
city:"",
state:"",
zip:'',
id:''
}
Here my Edit and Delete Function are there.I have two buttons to Edit and Delete.That two Functionality is not working..
import React, { Component } from 'react'
import axios from "axios";
import { Link } from 'react-router-dom';
import App from './App';
class Form extends Component {
constructor(props) {
super(props)
this.state = {
data:[],
}
}
componentDidMount(){
fetch('http://localhost:3000/data')
.then(response => response.json())
.then(user => this.setState({data:user}))
}
editUser=(obj,index)=>{
console.log(obj,index)
this.setState({objEdit:obj})
}
deleteUser=(i)=>{
console.log("deleteUser called",i)
axios.delete("http://localhost:3000/data/"+this.state.data[i].id).then(res=>{
console.log()
}).catch((error)=>{
console.log("Error Occured")
})
}
render() {
return (
<div>
<div className="row">
<div className="col-sm-8">
<table className="table">
<thead>
<tr>
<th>First Name</th>
<th>Last Name</th>
<th>Tel</th>
<th>Address</th>
<th>City</th>
<th>State</th>
<th>Zip</th>
<th>Edit</th>
<th>Delete</th>
</tr>
</thead>
<tbody>
{this.state.data.map((obj,i)=>{
return <tr key={i}>{Object.keys(obj).map((property)=>{
return <td key={property}>{obj[property]}</td>
})}<td><button onClick={()=>{this.editUser(obj,i)}} className="btn btn-info">Edit</button></td>
<td><button onClick={()=>{this.deleteUser(i)}} className="btn btn-danger">Delete</button></td></tr>
})}
</tbody>
<Link to ="/"> <button type="button" className="btn btn-primary" >Back</button></Link>
</table>
</div>
</div>
</div>
)
}
}
export default Form;

Related

Error: Too many re-renders. React limits the number of renders to prevent an infinite loop. Error in Contact.js file

I am trying to get my form populated when I click on the edit pencil button but I keep getting the error 'to many re-renders'. Anyone can help here? down below my two files
I am using firebase to pull out data from a collection and basically I am trying to build a simple application where you can display data from that database and then eventually edit it or delete it
Contact.js
import React, { useState, useEffect } from "react";
import ContactForm from "./ContactForm";
import firebaseDb from "../firebase";
const Contacts = () => {
var [learnerObjects, setLearnerObjects] = useState({});
var [currentId, setCurrentId] = useState("");
useEffect(() => {
firebaseDb.child("learners").on("value", (snapshot) => {
if (snapshot.val() != null)
setLearnerObjects({
...snapshot.val(),
});
});
}, []);
const addOrEdit = (obj) => {
firebaseDb.child("learners").push(obj, (err) => {
if (err) console.log(err);
});
};
return (
<>
<div class="jumbotron jumbotron-fluid">
<div class="container">
<h1 class="display-4 text-center">Contact Register</h1>
</div>
</div>
<div className="row">
<div className="col-md-5">
<ContactForm
{...setCurrentId({ addOrEdit, currentId, learnerObjects })}
/>
</div>
<div className="col-md-7">
<table className="table table-borderless table-stripped">
<thead className="thead-light">
<tr>
<th>First Name</th>
<th>Last Name</th>
<th>email</th>
<th>score</th>
<th>Edit</th>
</tr>
</thead>
<tbody>
{Object.keys(learnerObjects).map(id => {
return (
<tr key={id}>
<td>{learnerObjects[id].firstName}</td>
<td>{learnerObjects[id].lastName}</td>
<td>{learnerObjects[id].email}</td>
<td>{learnerObjects[id].score}</td>
<td>
<a
className="btn text-primary"
onClick={() => {
setCurrentId(id)
}}
>
<i className="fas fa-pencil-alt"></i>
</a>
<a className="btn text-danger">
<i className="fas fa-trash-alt"></i>
</a>
</td>
</tr>
);
})}
</tbody>
</table>
</div>
</div>
</>
);
};
export default Contacts;
ContactForm.js
import React, { useEffect, useState } from "react";
const ContactForm = (props) => {
const initialFieldValues = {
firstName: "",
lastName: "",
email: "",
score: 0,
};
var [values, setValues] = useState(initialFieldValues);
useEffect(() => {
if (props.currentId === '')
setValues({
...initialFieldValues,
});
else
setValues({
...props.learnerObjects[props.currentId],
});
}, [props.currentId, props.learnerObjects]);
const handleInputChange = (e) => {
var { name, value } = e.target;
setValues({
...values,
[name]: value,
});
};
const handleFormSubmit = (e) => {
e.preventDefault();
props.addOrEdit(values);
};
return (
<form autoComplete="off" onSubmit={handleFormSubmit}>
<div className="form-group input-group">
<div className="input-group-prepend">
<div className="input-group-text">
<i className="fas fa-user"></i>
</div>
</div>
<input
className="form-control"
placeholder="first name"
name="firstName"
value={values.firstName}
onChange={handleInputChange}
/>
</div>
<div className="form-row">
<div className="form-group input-group col-md-6">
<div className="input-group-prepend">
<div className="input-group-text">
<i className="fas fa-user"></i>
</div>
</div>
<input
className="form-control"
placeholder="last name"
name="lastName"
value={values.lastName}
onChange={handleInputChange}
/>
</div>
<div className="form-group input-group col-md-6">
<div className="input-group-prepend">
<div className="input-group-text">
<i className="fas fa-user"></i>
</div>
</div>
<input
className="form-control"
placeholder="email"
name="email"
value={values.email}
onChange={handleInputChange}
/>
</div>
</div>
<div className="form-group">
<textarea
className="form-control"
placeholder="score"
name="score"
value={values.score}
onChange={handleInputChange}
/>
</div>
<div className="form-group">
<input
type="submit"
value="Save"
className="btn btn-primary btn-block"
/>
</div>
</form>
);
};
export default ContactForm;
You are calling {...setCurrentId({ addOrEdit, currentId, learnerObjects })} on render.
You are updating the useState hook on render, which results in a rerender during which you are again updating the hook resulting in an infinity loop.
You need to update the state somewhere that is not executed on every render.

Edit and Delete functionality is not working as Excepted

I Have a form,when I submit the details of that form,It will redirect to next page and date will display there. There itself I have two buttons to Edit and Delete.That two Functionality is not working..
Can you help me in this?? Thanks in Advance..
import React, { Component } from 'react';
import axios from "axios";
import {withRouter} from 'react-router';
class App extends Component {
constructor(props) {
super(props)
this.state = {
data:[],
objEdit:obj
}
}
// handleInput(e){
// this.state.objEdit[e.target.name] = e.target.value
// this.setState({objEdit:this.state.objEdit})
// }
handleInput(e){
this.setState({
objEdit:{...this.state.objEdit, [e.target.name] : e.target.value}
})
}
updateUser = () =>{
console.log(this.state.objEdit)
const objEdit = {...this.state.objEdit, id: null};
axios.post("http://localhost:3000/data/", objEdit).then(()=>{
this.props.history.push('/Form')
}).catch((error)=>{
console.log("Error Occured")
})
}
render() {
return (
<div>
<div className="col-sm-4">
<form>
<div className="form-group">
<label htmlFor="fname">First Name</label>
<input type="text" className="form-control" name="fname" placeholder="Enter First Name" value={this.state.objEdit.fname} onChange={(e)=>{this.handleInput(e)}}/>
</div>
<div className="form-group">
<label htmlFor="lname">Last Name</label>
<input type="text" className="form-control" name="lname" placeholder="Enter First Name" value={this.state.objEdit.lname} onChange={(e)=>{this.handleInput(e)}}/>
</div>
<div className="form-group">
<label htmlFor="tel">Tel</label>
<input type="text" className="form-control" name="tel" placeholder="Tel" value={this.state.objEdit.tel} onChange={(e)=>{this.handleInput(e)}}/>
</div>
<div className="form-group">
<label htmlFor="address">Address</label>
<input type="text" className="form-control" name="address" placeholder="Enter First Name" value={this.state.objEdit.address} onChange={(e)=>{this.handleInput(e)}}/>
</div>
<div className="form-group">
<label htmlFor="fname">City</label>
<input type="text" className="form-control" name="city" placeholder="Enter First Name" value={this.state.objEdit.city} onChange={(e)=>{this.handleInput(e)}}/>
</div>
<div className="form-group">
<label htmlFor="state">State</label>
<input type="text" className="form-control" name="state" placeholder="Enter First Name" value={this.state.objEdit.state} onChange={(e)=>{this.handleInput(e)}}/>
</div>
<div className="form-group">
<label htmlFor="zip">Zip</label>
<input type="text" className="form-control" name="zip" placeholder="Enter First Name" value={this.state.objEdit.zip} onChange={(e)=>{this.handleInput(e)}}/>
</div>
<button type="button" className="btn btn-primary" onClick={this.updateUser}>Submit</button>
</form>
</div>
</div>
// </div>
)
}
}
export default withRouter(App);
Here my Edit and Delete Function are there.I have two buttons to Edit and Delete.That two Functionality is not working..
let obj={
fname:"",
lname:"",
tel:"",
address:"",
city:"",
state:"",
zip:'',
id:''
}
import React, { Component } from 'react'
import axios from "axios";
import { Link } from 'react-router-dom';
class Form extends Component {
constructor(props) {
super(props)
this.state = {
data:[],
}
}
componentDidMount(){
fetch('http://localhost:3000/data')
.then(response => response.json())
.then(user => this.setState({data:user}))
}
editUser=(obj,index)=>{
console.log(obj,index)
this.setState({objEdit:obj})
}
deleteUser=(i)=>{
console.log("deleteUser called",i)
axios.delete("http://localhost:3000/data/"+this.state.data[i].id).then(res=>{
console.log()
}).catch((error)=>{
console.log("Error Occured")
})
}
render() {
return (
<div>
<div className="row">
<div className="col-sm-8">
<table className="table">
<thead>
<tr>
<th>First Name</th>
<th>Last Name</th>
<th>Tel</th>
<th>Address</th>
<th>City</th>
<th>State</th>
<th>Zip</th>
<th>Edit</th>
<th>Delete</th>
</tr>
</thead>
<tbody>
{this.state.data.map((obj,i)=>{
return <tr key={i}>{Object.keys(obj).map((property)=>{
return <td key={property}>{obj[property]}</td>
})}<td><button onClick={()=>{this.editUser(obj,i)}} className="btn btn-info">Edit</button></td>
<td><button onClick={()=>{this.deleteUser(i)}} className="btn btn-danger">Delete</button></td></tr>
})}
</tbody>
<Link to ="/"> <button type="button" className="btn btn-primary" >Back</button></Link>
</table>
</div>
</div>
</div>
)
}
}
export default Form;
Delete is a simple. As you are iterating over local state for your data, you need to delete the data from local state when you get success from delete axios call,
deleteUser=(i)=>{
console.log("deleteUser called",i)
axios.delete("http://localhost:3000/data/"+this.state.data[i].id).then(res=>{
console.log("success");
this.state.data.splice(i,1); //This will delete data fro local state.
}).catch((error)=>{
console.log("Error Occured")
})
}
Now for update you cannot directly setState state from some other component where you don't have any relation.
this.setState({objEdit:obj})
This cannot be done, because objEdit is from App component. You don't have any relation between App and Form component.
One way is you can pass obj like, (Just an idea)
editUser=(obj,index)=>{
console.log(obj,index)
this.props.history.push({
pathname:"/", //probablt this is for App component
state: {objEdit : JSON.stringify(obj)}
})
}
Of course you need to wrap Form component using withRouter,
export default withRouter(Form)
Now in App component you can get this data in componentDiMount,
componentDidMount(){
let objEdit = JSON.parse(this.props.location.state.objEdit)
if(objEdit){
this.setState({objEdit})
}
}
Now you will get pre-filled values in your form, you just need to handle the update button functionality.
In your update function you are adding id manually,
const objEdit = {...this.state.objEdit, id: null};
But in this case you need to have check that if objEdit alreay have id, if yes then you need to hit the update API call.

when button is clicked, Form is redirected to another page But Data is not updating

I am giving details in the form and clicking the submit button to populate the data in next page..So, on submit button I have given Link to redirect to the next page.In that page the data should display..But before submission of the data, it is redirecting me to next page and the data I am not able to fetch,But once I refresh the page I am able to see the updated value, Same happening with DELETE button also.
Can you help me in this?? Thanks in Advance.
export default class App extends Component {
constructor(props) {
super(props)
this.state = {
data:[],
objEdit:obj
}
}
handleInput(e){
this.state.objEdit[e.target.name] = e.target.value
this.setState({objEdit:this.state.objEdit})
}
updateUser = () =>{
console.log(this.state.objEdit)
this.state.objEdit.id=null
axios.post("http://localhost:3000/data/",this.state.objEdit).then(res=>{
console.log()
}).catch((error)=>{
console.log("Error Occured")
})
}
render() {
return (
<div>
<div className="col-sm-4">
<form>
<div className="form-group">
<label htmlFor="fname">First Name</label>
<input type="text" className="form-control" name="fname" placeholder="Enter First Name" value={this.state.objEdit.fname} onChange={(e)=>{this.handleInput(e)}}/>
</div>
<div className="form-group">
<label htmlFor="lname">Last Name</label>
<input type="text" className="form-control" name="lname" placeholder="Enter First Name" value={this.state.objEdit.lname} onChange={(e)=>{this.handleInput(e)}}/>
</div>
<div className="form-group">
<label htmlFor="tel">Tel</label>
<input type="text" className="form-control" name="tel" placeholder="Tel" value={this.state.objEdit.tel} onChange={(e)=>{this.handleInput(e)}}/>
</div>
<div className="form-group">
<label htmlFor="address">Address</label>
<input type="text" className="form-control" name="address" placeholder="Enter First Name" value={this.state.objEdit.address} onChange={(e)=>{this.handleInput(e)}}/>
</div>
<div className="form-group">
<label htmlFor="fname">City</label>
<input type="text" className="form-control" name="city" placeholder="Enter First Name" value={this.state.objEdit.city} onChange={(e)=>{this.handleInput(e)}}/>
</div>
<div className="form-group">
<label htmlFor="state">State</label>
<input type="text" className="form-control" name="state" placeholder="Enter First Name" value={this.state.objEdit.state} onChange={(e)=>{this.handleInput(e)}}/>
</div>
<div className="form-group">
<label htmlFor="zip">Zip</label>
<input type="text" className="form-control" name="zip" placeholder="Enter First Name" value={this.state.objEdit.zip} onChange={(e)=>{this.handleInput(e)}}/>
</div>
{/* <button onClick={this.updateUser} type="button">Add</button> */}
<Link to="/Form"> <button type="button" className="btn btn-primary" onClick={this.updateUser}>Submit</button></Link>
</form>
</div>
</div>
// </div>
)
}
}
let obj={
fname:"",
lname:"",
tel:"",
address:"",
city:"",
state:"",
zip:'',
id:''
}
class Form extends Component {
constructor(props) {
super(props)
this.state = {
data:[],
}
}
componentDidMount(){
fetch('http://localhost:3000/data')
.then(response => response.json())
.then(user => this.setState({data:user}))
}
editUser=(obj,index)=>{
console.log(obj,index)
this.setState({objEdit:obj})
}
deleteUser=(i)=>{
console.log("deleteUser called",i)
axios.delete("http://localhost:3000/data/"+this.state.data[i].id).then(res=>{
console.log()
}).catch((error)=>{
console.log("Error Occured")
})
}
render() {
return (
<div>
<div className="row">
<div className="col-sm-8">
<table className="table">
<thead>
<tr>
<th>First Name</th>
<th>Last Name</th>
<th>Tel</th>
<th>Address</th>
<th>City</th>
<th>State</th>
<th>Zip</th>
<th>Edit</th>
<th>Delete</th>
</tr>
</thead>
<tbody>
{this.state.data.map((obj,i)=>{
return <tr key={i}>{Object.keys(obj).map((property)=>{
return <td key={property}>{obj[property]}</td>
})}<td><button onClick={()=>{this.editUser(obj,i)}} className="btn btn-info">Edit</button></td>
<td><button onClick={()=>{this.deleteUser(i)}} className="btn btn-danger">Delete</button></td></tr>
})}
</tbody>
</table>
</div>
</div>
</div>
)
}
}
export default Form;
When I Click on SUbmit Button, It should redirect me to next page with updated values And edit and delete button also should work properly without refreshing the page.
You need to use the history object of react-router to goto the next page after you get the response form the api call. When you use Link, it redirects to the page directly.
Also,
handleInput(e){
this.state.objEdit[e.target.name] = e.target.value
this.setState({objEdit:this.state.objEdit})
}
(and)
this.state.objEdit.id=null
Why are you even doing this? You shouldn't be mutating the state object.
handleInput(e){
this.setState({
objEdit:{...this.state.obj, [e.target.name] : e.target.value}
})
}
import {withRouter} from 'react-router';
.
.
.
updateUser = () =>{
console.log(this.state.objEdit)
// this.state.objEdit.id=null
const objEdit = {...this.state.objEdit, id: null};
axios.post("http://localhost:3000/data/", objEdit).then(res=>{
console.log(res)
this.props.history.push('/Form')
}).catch((error)=>{
console.log("Error Occured")
})
}
.
.
.
// remove the Link.
<button
type="button"
className="btn btn-primary"
onClick={this.updateUser}
>
Submit
</button>
.
.
.
export default withRouter(App)
You can do the same for others.

Mapping objects in an array to table in React

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

Reactjs - Form validation

Can anybody help me, I'm really struggling with the validation form in React, I was trying also with some library but I'm doing something wrong.
I want to validate both to be required and number to be a number.
class Hello extends React.Component {
constructor() {
super();
this.state = {
firstname: '',
number: '',
};
}
onChange = (event) => {
this.setState({ [event.target.name]: event.target.value });
}
onSubmit = (event) => {
event.preventDefault();
console.log('Submited');
}
render() {
return (
<div>
<form className="form-horizontal" onSubmit={this.onSubmit}>
<div className="form-group">
<label className="col-sm-2 control-label">Name</label>
<div className="col-sm-10">
<input type="text" name="firstname" className="form-control" onChange={this.onChange} placeholder="Firstname" />
</div>
</div>
<div className="form-group">
<label className="col-sm-2 control-label">Number</label>
<div className="col-sm-10">
<input type="text" name="number" className="form-control" onChange={this.onChange} placeholder="Number" />
</div>
</div>
<div className="form-group">
<div className="col-sm-offset-2 col-sm-10">
<button type="submit" className="btn btn-success">Submit</button>
</div>
</div>
</form>
<h3>{this.state.firstname}</h3>
<h3>{this.state.number}</h3>
</div>
);
}
}

Resources