Manage multiple form inputs and it's value via React state - javascript

Let me start with an example so you guys can know what is the issue and what I want to achieve.
In my project I'll have multiple user form on the same page and number of forms will be dynamic (depends on user number if there are 3 users then 3 forms, if 10 users then 10 forms etc).
Let's assume all forms will have 3 fields (keep it simple here) like firstName , middleName , lastName.
Now let assume we have 3 users so 3 inputs will appear on the page.
<form>
<input type="text" name="firstName" value="" />
<input type="text" name="middleName" value="" />
<input type="text" name="lastName" value="" />
</form>
We have 3 users this time so above form will appear 3 times. Here actually what I have taken only one form for all 3 users. What I have done is shown below.
<form>
for (let i = 1; i <= 3; i++) {
<input type="text" name="firstName" value="" />
<input type="text" name="middleName" value="" />
<input type="text" name="lastName" value="" />
}
<input type="submit" value="Submit">Apply</button>
</form>
When user submits the form I want an array of value for each form field.
What and How result I want is below.
['tome hanks' , 'shahrukh khan', 'john'] // firstname of all 3 users
['tome hanks' , 'shahrukh khan', 'john'] // middlename of all 3 users
['tome hanks' , 'shahrukh khan', 'john'] // lastname of all 3 users
I have tried this tutorial but not exactly what I need.
Maybe I can achieve this using React state but don't know how?
If Redux is helpful than it's fine for me.

class App extends React.Component {
constructor(props) {
super(props);
this.state = {
users: [
{ firstName: 'John1', middleName: 'Daniel1', lastName: 'Paul1' },
{ firstName: 'John2', middleName: 'Daniel2', lastName: 'Paul2' },
{ firstName: 'John3', middleName: 'Daniel3', lastName: 'Paul3' },
{ firstName: 'John4', middleName: 'Daniel4', lastName: 'Paul4' },
],
};
}
_onChangeUser = (index, field, event) => {
const newValue = event.target.value;
this.setState(state => {
const users = [
...state.users.slice(0, index),
{
...state.users[index],
[field]: newValue,
},
...state.users.slice(index + 1),
];
return {
users,
};
});
};
_onSubmit = event => {
event.preventDefault();
// Do something with this.state.users.
console.log(this.state.users);
};
render() {
return (
<div className="App">
<form onSubmit={this._onSubmit}>
{this.state.users.map((user, index) => (
<div key={index}>
<input
value={user.firstName}
onChange={this._onChangeUser.bind(this, index, 'firstName')}
/>
<input
value={user.middleName}
onChange={this._onChangeUser.bind(this, index, 'middleName')}
/>
<input
value={user.lastName}
onChange={this._onChangeUser.bind(this, index, 'lastName')}
/>
</div>
))}
<button type="submit">Submit</button>
</form>
</div>
);
}
}
ReactDOM.render(
<App />,
document.getElementById('root')
);
<script crossorigin src="https://unpkg.com/react#16/umd/react.development.js"></script>
<script crossorigin src="https://unpkg.com/react-dom#16/umd/react-dom.development.js"></script>
<div id="root"><div>

Ok. Declare your state variable as an array. Below should fulfill your requirement.
constructor(props){
super(props)
this.state={
firstNameArray:[],
middleNameArray:[],
lastNameArray:[],
fName:” “,
mName:””,
lName:””
}
this.changeFirstName = this.changeFirstName.bind(this);
this.changeMiddleName= this.changeMiddleName.bind(this);
this.changeLastName=this.changeLastName.bind(this);
}
changeFirstName(event){
this.setState({
firstNameArray:event.target.value,
fName: event.target.value
})
changeMiddleName(event){
this.setState({
middleNameArray: event.target.value,
mName: event.target.value
})
}
changeLastName(event){
this.setState({
lastNameArray: event.target.value,
lName: event.target.value
})
Call each function on your input field like below
<input type=‘text’ name=‘fName’ value= {this.state.fName} onChange={this.changeFirstName} />
Do it in the same way for other two input fields as well. Hope this answers your question.

Related

Why is only the last input value displayed on screen?

I'm having problem with my input fields. I got five of them. When i fill all of them and press the button to display them on the screen, only the last one I typed is displayed on all places... (this was hard to formulate, ask if you don't understand)
Here is when i want the output:
´´´
{this.state.new_array.map((char, i) => (
<li key={i}>
{`(${char.gender})
${char.name}
${char.height}
${char.eye_color}
${char.birth_year}`}
</li>
))}
´´´
Here's my input fields and button:
´´´
<input onChange={this.handleChange}></input>
<input onChange={this.handleChange}></input>
<input onChange={this.handleChange}></input>
<input onChange={this.handleChange}></input>
<input onChange={this.handleChange}></input>
<button onClick={this.addNewCharacter} }>Add character</button>
´´´
And here's my functions connected to button and inputs:
´´´
constructor(props){
super(props);
this.state = {
new_array: [],
nameFromInput: "",
heightFromInput: "",
birthyearFromInput: "",
genderFromInput: "",
eyecolorFromInput: ""
}
}
addNewCharacter = () => {
this.setState(oldState => ({
new_array: [...oldState.new_array, { // IM PRETTY SURE IT HAS TO DO WITH THIS FUCNTION?
name: this.state.nameFromInput,
height: this.state.heightFromInput,
birth_year: this.state.birthyearFromInput,
gender: this.state.genderFromInput,
eye_color: this.state.eyecolorFromInput
}]
}))
this.setState({showFavorites: true})
}
handleChange = event => {
this.setState({
nameFromInput: event.target.value,
heightFromInput: event.target.value,
birthyearFromInput: event.target.value,
genderFromInput: event.target.value,
eyecolorFromInput: event.target.value});
}
´´´
Why make something so easy complicated?
Here's a working sample in Codesandbox https://codesandbox.io/s/serene-hodgkin-d5kz9?file=/src/App.js
Solution posted below for brevity:
import React from "react";
export default class App extends React.Component {
constructor(props) {
super(props);
this.state = {
name: "",
height: "",
birthyear: "",
gender: "",
eyecolor: ""
};
}
handleChange = event => {
this.setState({
name: event.target.value,
height: event.target.value,
birthyear: event.target.value,
gender: event.target.value,
eyecolor: event.target.value
});
};
addNewCharacter = () => {
const { name, height, birth_year, gender, eye_color } = this.state;
this.setState({
new_array: {
name,
height,
birth_year,
gender,
eye_color
},
showFavorites: true
});
console.log(this.state);
};
render() {
return (
<div className="App">
<input onChange={this.handleChange} />
<input onChange={this.handleChange} />
<input onChange={this.handleChange} />
<input onChange={this.handleChange} />
<input onChange={this.handleChange} />
<button onClick={this.addNewCharacter}>Add character</button>
</div>
);
}
}
Every time you change any of the input fields' values, you're calling this.handleChange, the same function every time, with that input change Event passed as an argument.
No matter which input this event is fired from, every key in the state gets updated with the value from that input.
Something that might look a little better is:
generateHandleChange = key => event => {
this.setState({[key]: event.target.value});
};
and your inputs would look like this:
<input onChange={this.generateHandleChange('name')} />
<input onChange={this.generateHandleChange('height')} />
<input onChange={this.generateHandleChange('birth_year')} />
<input onChange={this.generateHandleChange('gender')} />
<input onChange={this.generateHandleChange('eye_color')} />
<button onClick={this.addNewCharacter}>Add character</button>

How to clear controlled forms in react-redux

I'm trying to clear a form in my react-redux component. I know that I should be able to clear them using setState() after a submit, but since I'm receiving all my data as props (via the redux store) is there an easy way to do this within the component itself?
class Postform extends Component {
constructor(props){
super(props)
this.state={
propertyName: ' enter name ',
footage: ' size in sqft ',
address: ' full address ',
price: ' $ 00.00 '
}
}
onChange =(e)=>{
this.setState({ [e.target.name] :e.target.value});
}
onSubmit = (e) =>{
e.preventDefault()
const newListing = {
propertyName: this.state.propertyName,
footage: this.state.footage,
address: this.state.address,
price: this.state.price
}
this.props.newProperty(newListing)
// my attempt to reset the state of the form (unsure how to accomplish this?)
this.setState({
propertyName: '',
footage: '',
address: '',
price: ''
})
};
render() {
return (
<div className="form">
<h2>Add Listing</h2>
<form onSubmit = {this.onSubmit}>
<div>
<label>your listing name</label><br/>
<input name="propertyName" type="text" onChange={this.onChange} placeholder={this.state.propertyName} />
</div>
<div>
<label>listing size </label><br/>
<input name="footage" onChange={this.onChange} placeholder={this.state.footage} />
</div>
<div>
<label>listing location </label><br/>
<input name="address" onChange={this.onChange} placeholder={this.state.address} />
</div>
<div>
<label>desired price </label><br/>
<input name="price" onChange={this.onChange} placeholder={this.state.price} />
</div>
<br/>
<button className="submitbtn" type="submit">Submit</button>
</form>
</div>
)
}
}
Postform.propTypes = {
newProperty: PropTypes.func.isRequired,
new: PropTypes.object
}
const mapStateToProps = state =>({
listings: state.listings.properties,
new: state.listings.newListing
});
export default connect(mapStateToProps, {newProperty})(Postform)
I checked around online and found a few solutions. I wanted to see if anyone could tell me based on my code if there would be a preferred way of achieving this?
Here all the different methods I found not sure which I should use based on my component though : https://redux-form.com/6.0.0-alpha.7/docs/faq/howtoclear.md/
Your approach seems valid to me, I would only do the job in a bit 'lazy' manner:
this.setState(Object.keys(this.state).forEach(key => this.state[key] = ''))
import { initialize, reset } from 'redux-form';
dispatch(initialize('formName', {})); // Clear form
// or
dispatch(reset('formName'));

Unable to type into React input field

I am unable to type any input into my input field. I am using React, and have already set a handleChange and a handleSubmit function. The first two input fields, for 'name' and 'email', take input just fine. But for 'favoriteCity', it doesn't seem to work.
I am wondering if it is due to a MongoDB error that I am getting.
class UserPage extends Component {
state = {
user: [],
newUser: {
name: '',
email: '',
favoriteCity: ''
}
}
getAllUsers = () => {
axios.get('/api/users')
.then(res => {
this.setState({ user: res.data })
})
}
componentDidMount() {
this.getAllUsers()
}
handleChange = event => {
const newUser = { ...this.state.newUser };
newUser[event.target.name] = event.target.value;
this.setState({ newUser: newUser});
}
handleSubmit = event => {
event.preventDefault()
axios.post('/api/users', this.state.newUser)
.then(res => {
this.props.history.push(`/users/${res.data._id}`)
})
}
render() {
return (
<div>
{ /* This shows a list of All Users */ }
{this.state.user.map(user => (
<div key={user._id}>
<Link to={`/users/${user._id}`}>{user.name}</Link>
</div>
))}
<h1>New User Page</h1>
<form onSubmit={this.handleSubmit}>
<label>Name: </label>
<input
type="text"
name="name"
placeholder="Name?"
value={this.state.newUser.name}
onChange={this.handleChange}
/>
<label>Email: </label>
<input
type="text"
name="email"
placeholder="Email?"
value={this.state.newUser.email}
onChange={this.handleChange}
/>
<label>Favorite City: </label>
<input
type="text"
name="city"
placeholder="Favorite City?"
value={this.state.newUser.favoriteCity}
onChange={this.handleChange}
/>
<Button
type="submit"
value="Submit"
variant="contained"
color="primary"
>
Create User
</Button>
</form>
</div>
);
}
}
export default UserPage;
Please help.
Weird that email works fine, from what you posted your handleChange function is only updating the name on the newUser.
What you should see is what you type in all the inputs appear in the name input.
To fix this, you should probably have separate change handlers for each input:
handleNameChange
handleEmailChange
...
You should also consider storing name, email etc.. at the root of your state instead of nesting them in an object, that'll simplify the handler functions code.

Update data in form. Stay editable. (React with Redux, sans redux-form)

Problem
I have a list of people. I want to:
Select a user to edit by clicking on their name.
Edit that user's information, so I can click the submit button and update the list.
If I click on a different name, I want to switch to that person's information without having to deliberately close the form first.
Everything works until #3. When I click on another person, the form, itself, does NOT update.
My Code
Update Component for the update form:
const UpdateForm = ({ updatePerson, personToUpdate, handleInputChange }) => {
let _name, _city, _age, _id;
const submit = (e) => {
e.preventDefault();
updatePerson({
name: _name.value,
city: _city.value,
age: _age.value,
_id: _id.value
});
};
return (
<div>
<form onSubmit={submit}>
<h3>Update Person</h3>
<label htmlFor="_id">Some Unique ID: </label>
<input type="text" name="_id" ref={input => _id = input} id="_id" defaultValue={personToUpdate._id} onChange={input => handleInputChange(personToUpdate)} required />
<br />
<label htmlFor="name">Name: </label>
<input type="text" name="name" ref={input => _name = input} id="name" defaultValue={personToUpdate.name} onChange={input => handleInputChange(personToUpdate)} />
<br />
<label htmlFor="city">City: </label>
<input type="text" name="city" ref={input => _city = input} id="city" defaultValue={personToUpdate.city} onChange={input => handleInputChange(personToUpdate)} />
<br />
<label htmlFor="age">Age: </label>
<input type="text" name="age" ref={input => _age = input} id="age" defaultValue={personToUpdate.age} onChange={input => handleInputChange(personToUpdate)} />
<br />
<input type="submit" value="Submit" />
</form>
</div>
);
};
export default UpdateForm;
Relevant parts of Person Component:
class Person extends Component {
nameClick() {
if (this.props.person._id !== this.props.personToUpdate._id) {
this.props.setForUpdate(this.props.person);
this.forceUpdate();
}
else {
this.props.toggleUpdatePersonPanel();
}
}
render() {
return (
<div>
<span onClick={this.nameClick}>
{this.props.person.name} ({this.props.person.age})
</span>
</div>
);
}
}
export default Person;
Relevant parts of PeopleList, which holds Persons:
class PeopleList extends Component {
render() {
return(
<div>
{this.props.people.map((person) => {
return <Person
key={person._id}
person={person}
updatePersonPanel={this.props.updatePersonPanel}
setForUpdate={this.props.setForUpdate}
personToUpdate={this.props.personToUpdate}
/>;
})}
</div>
);
}
} // end class
export default PeopleList;
Form Reducer, with just the relevant actions:
export default function formReducer(state = initialState.form, action) {
let filteredPeople;
switch (action.type) {
case TOGGLE_UPDATE_PANEL:
return Object.assign({}, state, { updatePersonPanel: false }, { personToUpdate: {
_id: "",
name: "",
city: "",
age: ""
}});
case SET_FOR_UPDATE:
return Object.assign({}, state, { personToUpdate: action.person }, { updatePersonPanel: true });
case UPDATE_RECORD:
filteredPeople = state.people.filter((person) => {
return person._id === action.person._id ? false : true;
}); // end filter
return Object.assign({}, state, { people: [ ...filteredPeople, action.person] }, { personToUpdate: {
_id: "",
name: "",
city: "",
age: ""
}}, { updatePersonPanel: false });
case HANDLE_INPUT_CHANGE:
return Object.assign({}, state, { personToUpdate: action.person });
default:
return state;
}
}
The relevant parts of my Initial State file:
form: {
people: [
{
_id: "adfpnu64",
name: "Johnny",
city: "Bobville",
age: 22
},
{
_id: "adf2pnu6",
name: "Renee",
city: "Juro",
age: 21
},
{
_id: "ad3fpnu",
name: "Lipstasch",
city: "Bobville",
age: 45
}
],
updatePersonPanel: false,
personToUpdate: {
_id: "",
name: "",
city: "",
age: ""
},
}
Attempts at a Solution( so far)
I have attempted to make the component a completely controlled component, by switching the form attribute to value instead of defaultValue. When I do this, the names switch just fine, but the form becomes unchangeable and useless.
My Questions
Almost all of the solutions to these kind of issues either recommend using redux-form or supply two-way binding solutions that work fine in React without reduce. I want to know how to do this with Redux without using redux-form or anything extra if possible. Is there a way to resolve this without touching lifecycle methods?
Conclusion (For now)
Well, for now, I settled for making my form uncontrolled and used some classic Js DOM methods and a lifecycle method to control the form. For whatever reason, once I employed some of the answer suggestions my browser ate up my CPU and crashed, presumably because there was some kind of infinite loop. If anyone has some further recommendations, I'd really appreciate it. For now I settle for this:
class UpdateForm extends Component {
constructor(props){
super(props);
this.submit = this.submit.bind(this);
}
componentWillReceiveProps(nextProps) {
if (nextProps.personToUpdate._id !== this.props.personToUpdate._id) {
document.getElementById("name").value = nextProps.personToUpdate.name;
document.getElementById("age").value = nextProps.personToUpdate.age;
document.getElementById("city").value = nextProps.personToUpdate.city;
}
}
submit(e) {
e.preventDefault();
this.props.updatePerson({
name: document.getElementById("name").value,
city: document.getElementById("city").value,
age: document.getElementById("age").value,
_id: this.props.personToUpdate._id
});
}
render() {
return (
<div>
<form onSubmit={this.submit}>
<h3>Update Person</h3>
Unique ID: {this.props.personToUpdate._id}
<br />
<label htmlFor="name">Name: </label>
<input type="text" name="name" id="name" ref="name" defaultValue={this.props.personToUpdate.name} required />
<br />
<label htmlFor="city">City: </label>
<input type="text" name="city" id="city" ref="city" defaultValue={this.props.personToUpdate.city} required />
<br />
<label htmlFor="age">Age: </label>
<input type="text" name="age" id="age" ref="age" defaultValue={this.props.personToUpdate.age} required />
<br />
<input type="submit" value="Update" />
</form>
</div>
);
}
} // end class
export default UpdateForm;
I'll be soon exploring redux-form because it is evident that forms as inputs and outputs are a wonky business. For now, my little app works.
Yes there is and you are on the right path. The way is to use value instead of defaultValue but you have to read the value from a state and then use the onChange handler to modify the state.
Something like
this.state = {inputText:''}
Then in the input field
<input value={this.state.inputText} onChange={this.handleChange}/>
And the handleChange function will be
handleChange(event){
this.setState({inputText:event.target.value})
}
Remember to bind the handleChange event in the constructor so you can pass it as this.handleChange in the input field's onChange prop.
Something like this
this.handleChange = this.handleChange.bind(this)
https://facebook.github.io/react/docs/forms.html - Here are the official docs regarding it
Also if you want to do it in redux the same sort of logic applies where this will be the input field
<input value={this.props.inputText} onChange={this.props.handleChange}/>
where inputText and handleChange are redux state and action respectively passed to the component via props
For your case I guess it has to be something like where you are 'reading' values from the people array and the action bound to the onChange modifies that value in the people array in the state.
<--EDIT-->
How it can be done for the case in point. Pass the people in the redux state as a people prop to the component. Pass an action changePeople(newPeople) to the component as a prop which takes an argument newPeople and changes the people in the redux state to have the value newPeople. Since people is nested in form you'll have to do some Object.assign etc to modify the state.
Now in the component using the people props populate the checkboxes using a map function. The map function takes a second parameter index so for each checkbox have a function which sets the local state variable currentPerson to the value of the index
this.props.people.map((person,index) =>
return <Checkbox onClick={()=>this.setState(currentPerson:index)}/>
)
So everytime you click on a checkbox the currentPerson points to the corresponding index.
Now the input fields can be
<input value={this.props.people[this.state.currentPerson].name} onChange={this.handleChange.bind(this,'name')}/>
This is for the 'name' input field. It reads from the currentPerson index of the people array which has been passed down as a prop.
This is how the handleChange will be like
handleChange(property,event){
const newPeople = [
...this.props.people.slice(0, this.state.currentPerson),
Object.assign({}, this.props.people[this.state.currentPerson], {
[property]: event.target.value
}),
...this.props.people.slice(this.state.currentPerson + 1)
]
this.props.changePeople(newPeople)
}
The handleChange takes a property (so you don't have to write separate handlers for each input field). The newPeople basically modifies the element at current index this.state.currentPerson in the people passed from props (ES6 syntax being used here. If you have doubts do ask). Then it is dispatched using the changePeople action which was also passed as props.

React form, to submit object which is then pushed to array

I'm new to React and unsure about how to do this.
I have an array of objects that I have mapped through and rendered in my view. What I want to do is set up a form that will submit the values of each field to the corresponding properties of a new object, but I'm not sure how to go about doing this.
Here is my initial data, which is rendered in the view:
contactArray = [
{
name: 'John'
email: 'john#email.com'
number: 111-111-111
},
{
name: 'Dave'
email: 'dave#email.com'
phone: '222-222-222'
}
]
Then I have a form:
class InputForm extends Component {
render() {
return (
<form>
<input type='text' onChange={this.handleChange}/>
<input type='text' onChange={this.handleChange}/>
<input type='text' onChange={this.handleChange}/>
<button type='submit' onSubmit={this.handleSubmit}>SUBMIT</button>
</form>
)
}
Then I assume I declare the state as this:
constructor(props) {
super(props);
this.state = {
name: '',
email: '',
phone: ''
}
}
Then the submission function I don't really know how to handle...
handleSubmit() {
// not sure about this...
this.setState({
name: // ????
email: // ????
phone: // ????
})
}
And then I want to clear the submit form, as well as the object that is used to push the new object, which is now in the array (I hope that makes sense...)
So, I'm not even sure how to use state in this scenario, but ultimately I want to push() the new object to the array that is rendered, with all the properties as they were completed in the form.
Sorry I can't be more complete with my working up to this point, but would at least appreciate some pointers on this!
From what I understand you want to push new people to the existing contactArray ? I will share with my way of doing it. Have a look:
const contactArray = [
{
name: 'John',
email: 'john#email.com',
phone: '111-111-111'
},
{
name: 'Dave',
email: 'dave#email.com',
phone: '222-222-222'
}
];
class Form extends React.Component {
constructor() {
super();
this.state = {
contacts: contactArray
};
this.handleSubmit = this.handleSubmit.bind(this);
}
handleSubmit(e) {
e.preventDefault();
const
{ contacts } = this.state,
name = this.refs.name.value,
email = this.refs.email.value,
phone = this.refs.phone.value;
this.setState({
contacts: [...contacts, {
name,
email,
phone
}]
}, () => {
this.refs.name.value = '';
this.refs.email.value = '';
this.refs.phone.value = '';
});
}
render() {
const { contacts } = this.state;
console.log('message',this.state.contacts);
return (
<div>
<h2>Add Someone</h2>
<form onSubmit={this.handleSubmit}>
<input type="text" ref="name" placeholder="name" />
<input type="text" ref="email" placeholder="email" />
<input type="text" ref="phone" placeholder="phone" />
<button type="submit">Submit</button>
</form>
<h2>Exsiting contacts:</h2>
<ul>
{contacts.map((contact) =>
<li>{`Name: ${contact.name} Email: ${contact.email} Phone: ${contact.phone}`}</li>
)}
</ul>
</div>
)
}
}
ReactDOM.render(<Form />, document.getElementById('root'));
So first thing we do is save contactArray within our actual component where we are going to use it, next we decalre and bind our handleSubmit I am using refs for the inputs in order to get thier value. this.setState ({ contacts: [...contacts] , { Object }); Here we use the ES6 spread operator to pass all the existing contacts to our new state and add a new contact. { name, email, phone } Is exactly like doing { name:name, email:email ...} It's just a short-hand, this.setState({}, () => { Callback! }); In the callback function of this.setState({}); I am going to clear the input values. Live demo: http://codepen.io/ilanus/pen/qaXNmb
Here is another way you can do it, same results different approach.
const contactArray = [
{
name: 'John',
email: 'john#email.com',
phone: '111-111-111'
},
{
name: 'Dave',
email: 'dave#email.com',
phone: '222-222-222'
}
];
class Form extends React.Component {
constructor() {
super();
this.state = {
contacts: contactArray,
newContact: {
name: '',
email: '',
phone: ''
}
};
this.handleSubmit = this.handleSubmit.bind(this);
this.handleInput = this.handleInput.bind(this);
}
handleSubmit(e) {
e.preventDefault();
const { contacts, newContact } = this.state;
this.setState({
contacts: [...contacts, newContact],
}, () => {
for (let val in newContact) {
newContact[val] = ''; // Clear the values...
}
this.setState({ newContact });
});
}
handleInput(e, element) {
const { newContact } = this.state;
newContact[element] = e.target.value;
this.setState({ newContact });
}
render() {
const { contacts, newContact } = this.state;
const { name, email, phone } = newContact;
return (
<div>
<h2>Add Someone</h2>
<form onSubmit={this.handleSubmit}>
<input type="text" value={name} onChange={e => this.handleInput(e, 'name')} placeholder="name" />
<input type="text" value={email} onChange={e => this.handleInput(e, 'email')} placeholder="email" />
<input type="text" value={phone} onChange={e => this.handleInput(e, 'phone')} placeholder="phone" />
<button type="submit">Submit</button>
</form>
<h2>Exsiting contacts:</h2>
<ul>
{contacts.map((contact) =>
<li>{`Name: ${contact.name} Email: ${contact.email} Phone: ${contact.phone}`}</li>
)}
</ul>
</div>
)
}
}
ReactDOM.render(<Form />, document.getElementById('root'));
Live demo: http://codepen.io/ilanus/pen/LRjkgx
I highly recommend using the first example. as it's performance will be better :)
You don't need to set state for all the inputs. If you do, it'll be a problem when you have more input fields. See the below fiddle, in that, I've used a single state to store the entire contacts. When you press the submit button, it get all the values from the input and save it to the state. Hope it helps!
Fiddle: http://jsfiddle.net/Pranesh456/8u4uz5xj/1/
[UPDATE]
e.value = null will clear the value inside the form. By this, you'll able to reset the entire form.
slice() is used to make a copy of the array in the state. As assignment of array is a reference to the original array, any operation on the new array will also reflect in the original array.
Example:
a = [1,2,4]
b = a
b.push(7)
console.log(b) //prints [1,2,4,7]
console.log(a) //also prints [1,2,4,7]
But
b = a.slice() //creates a copy of a
b.push(7)
console.log(b) //prints [1,2,4,7]
console.log(a) //also prints [1,2,4]
More details about slice
By doing this, you'll not mutate the existing state, which is a good practice.
Hope it help!!

Categories

Resources