6

I am trying to make a simple contact form using React. Eventually I will send the data collected from the state to a database, but for right now I am trying to just get it to console log the correct values.

Right now, the email field overrides the name field and when I console log both states, name shows up and email is undefined. Here is my React Component

import React, { Component, PropTypes } from 'react';
import ContactData from '../data/ContactData.js';


class FormContact extends Component {
    constructor(props) {
        super(props)
        this.state = {
            name: '',
            email: '',
            textArea: ''
        }
    }

    handleChange(event) {
        event.preventDefault();
        this.setState({
            name: event.target.value,
            email: event.target.email
        })
    }

    handleSubmit(event) {
        event.preventDefault();
        console.log(this.state.name + ' ' + this.state.email);
    }

    render() {
        return (
            <form onSubmit={this.handleSubmit.bind(this)}>
                <label> Name:
                    <input type="text" placeholder="Name" value={this.state.name} onChange={this.handleChange.bind(this)} />
                </label><br />
                <label> Email:
                    <input type="text" placeholder="Email" value={this.state.email} onChange={this.handleChange.bind(this)}/>
                </label><br />
                    <input className="btn btn-primary" type="submit" value="Submit" />
           </form>
        )
    }
}

FormContact.PropTypes = {
    subName: PropTypes.string,
    subEmail: PropTypes.string
}

FormContact.defaultProps = {
    subName: 'Sam',
    subEmail: ''
}

class Contact extends Component {
    render() {
        return (
            <div>
                <h1>CONTACT PAGE</h1>
                <FormContact />
            </div>
        )
    }
}


export default Contact;

2 Answers 2

19

If I understand what you want, you could do it as follows :

  • Add an empty object in your state for the form values

    formValues: {}

  • Add the name attribute to your fields

    <input name="name" .... /> <input name="email" .... />

  • then depending on that name update your state in handleChange function

    let formValues = this.state.formValues;
    let name = event.target.name; // Field name
    let value = event.target.value; // Field value
    
    formValues[name] = value;
    
    this.setState({formValues})
    
  • And if the values go one level deeper, you could use value={this.state.formValues["name"]} instead of value={this.state.name} - where name is the value of the name attribute of your input field

Thus, everything together should be as follows :

class Test extends React.Component {
    constructor(props) {
        super(props)
        this.state = {
            formValues: {}
        }
    }

    handleChange(event) {
        event.preventDefault();
        let formValues = this.state.formValues;
        let name = event.target.name;
        let value = event.target.value;

        formValues[name] = value;

        this.setState({formValues})
    }

    handleSubmit(event) {
        event.preventDefault();
        console.log(this.state.formValues);
    }

        render(){
        return (
        <form onSubmit={this.handleSubmit.bind(this)}>
                <label> Name:
                    <input type="text" name="name" placeholder="Name" value={this.state.formValues["name"]} onChange={this.handleChange.bind(this)} />
                </label><br />
                <label> Email:
                    <input type="text" name="email" placeholder="Email" value={this.state.formValues["email"]} onChange={this.handleChange.bind(this)}/>
                </label><br />
                    <input className="btn btn-primary" type="submit" value="Submit" />
           </form>
      )
    }
}

React.render(<Test />, document.getElementById('container'));

Here is fiddle.

Hope this helps.

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

5 Comments

I'll set this up after work - looks like what I was looking for, thank you!
FormContact is changing an uncontrolled input of type text to be controlled. Input elements should not switch from uncontrolled to controlled (or vice versa). Decide between using a controlled or uncontrolled input element for the lifetime of the component. - - Produces this error
To fix the uncontrolled input issue, you have to initialise the formValues object with empty strings for name and email.
@boky your fiddle is busted when I click on it.
@unflores Updated.
1

The reference to event.target.email does not exist on the event element. The value of a text input from an inline-event handler would be event.target.value for both email and name. The quick solution is to create a separate handler for each input:

handleChangeName(event) { 
  event.preventDefault();
  this.setState({ name: event.target.value });  //<-- both use the same reference
}                                               //    to get the contextual value
handleChangeEmail(event) {                      //    from the inputs v
  event.preventDefault();                       //                    |
  this.setState({ email: event.target.value }); //<--------------------
}

2 Comments

Yeah I know two different handlers will work, but I feel like there has to be a way to handle it all at once otherwise bigger form submissions would have a TON of handler functions. There must be a better way (not using refs, because I heard those were bad)
I see. In that case, have you tried passing an extra parameter to bind: which be the string name of the value you want to change? Then the handleChange method could use that value in the setState dynamically. Another option would be to create a Higher Order Component that wraps an input and effectively makes it a 'dumb' controlled input.

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.