3

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: '[email protected]'
    number: 111-111-111
  },
  {
    name: 'Dave'
    email: '[email protected]'
    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!

1
  • Please add the update section from your question as a comment on Pranesh's answer. Replies to answers should not be posted on the question itself but should be posted/discussed on the comment section of the respective answer(s) posted. Commented May 30, 2018 at 22:26

2 Answers 2

5

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: '[email protected]',
    phone: '111-111-111'
  },
  {
    name: 'Dave',
    email: '[email protected]',
    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: '[email protected]',
    phone: '111-111-111'
  },
  {
    name: 'Dave',
    email: '[email protected]',
    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 :)

Sign up to request clarification or add additional context in comments.

4 Comments

Thanks. I have read that you should avoid using refs where possible - I've never used them so am unsure of their limitations... can you clarify at all on this?
@Paulos3000 why not use refs? I have added another example of the form summation without refs too.
I'm not sure why exactly, I read it here - tutorialspoint.com/reactjs/reactjs_refs.htm - I just wanted to better understand when they're appropriate rather than rely on them and later discover their drawbacks.
codepen broken do you have another example
4

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]

  1. e.value = null will clear the value inside the form. By this, you'll able to reset the entire form.
  2. 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!!

8 Comments

Thanks. Although the JSFiddle is more or less what I put in my OP... Did you send the wrong link?
@Paulos3000 Hey! Sorry! Updated the link.
Really helpful - thanks. Please take a look at my update, there's a couple of things I wasn't sure about in your code...
Just a note - an alternative way to clear the form elements after submission is to call .reset() on the form element on submission. I just found that out and thought it might be useful for anyone facing this scenario...
@Paulos3000 That's helps! Thanks!
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.