2

I'm new to React and have run into a problem building a simple form component. There are four input fields and four matching onChange handlers. All of them are effectively identical:

handleEmailChange(event) {
    this.setState({email: event.target.value});
}

handlePasswordChange(event) {
    this.setState({password: event.target.value});
}

handleFirstNameChange(event) {
    this.setState({firstName: event.target.value});
}

handleLastNameChange(event) {
    this.setState({lastName: event.target.value});
}

render() {
    return (
        <div>
            <label>Email: </label>
            <input type="text" name="email" placeholder="Email" value={this.state.email} onChange={this.handleEmailChange} />
            <label>Password: </label>
            <input type="password" name="password" placeholder="Password" value={this.state.password} onChange={this.handlePasswordChange} />
            <label>First name: </label>
            <input type="text" name="firstName" placeholder="First name" value={this.state.firstName} onChange={this.handleFirstNameChange} />
            <label>Last name: </label>
            <input type="text" name="lastName" placeholder="Last name" value={this.state.lastName} onChange={this.handleLastNameChange} />
            <input type="submit" value="Add User" onClick={this.handleSubmit} />
        </div>
    )
}

Three of these work just fine. The password handler, however, throws a TypeError exception "event.target is undefined" when the page tries to render. If I remove the handler and input element, the app renders. If I copy and paste one of the other handlers and inputs and change the relevant names, it still throws the exception. If I change the input type from "password" to "text" it still throws the exception. I cannot figure out why a seemingly identical piece of code is throwing this exception but every other piece of code like it works just fine.

In case it matters, the code for the entire component is

class AddUserForm extends Component {
constructor(props) {
    super(props);
    this.state = {
        email: '',
        password: '',
        firstName: '',
        lastName: ''
    };

    this.validate = this.validate.bind(this);
    this.handleSubmit = this.handleSubmit.bind(this);
    this.handleEmailChange = this.handleEmailChange.bind(this);
    this.handlePasswordChange = this.handlePasswordChange(this);
    this.handleFirstNameChange = this.handleFirstNameChange.bind(this);
    this.handleLastNameChange = this.handleLastNameChange.bind(this);
}

validate(user) {
    return (user.email && user.password && user.firstName && user.lastName);
}

handleSubmit(event) {
    let newUser = {
        email: this.state.email,
        password: this.state.password,
        firstName: this.state.firstName,
        lastName: this.state.lastName
    };

    if (AddUserForm.validate(newUser)) {
        fetch(`http://localhost:3001/admin/addUser`, {
            method: 'post',
            headers: new Headers({
                'Content-Type': 'application/x-www-form-urlencoded',
            }),
            body: JSON.stringify(newUser)
        })
            .then( res => {
                const copy = [newUser].concat(this.state.users);
                this.setState({users: copy});
            })
    }

    event.preventDefault();
}

handleEmailChange(event) {
    this.setState({email: event.target.value});
}

handlePasswordChange(event) {
    this.setState({password: event.target.value});
}

handleFirstNameChange(event) {
    this.setState({firstName: event.target.value});
}

handleLastNameChange(event) {
    this.setState({lastName: event.target.value});
}

render() {
    return (
        <div>
            <label>Email: </label>
            <input type="text" name="email" placeholder="Email" value={this.state.email} onChange={this.handleEmailChange} />
            <label>Password: </label>
            <input type="password" name="password" placeholder="Password" value={this.state.password} onChange={this.handlePasswordChange} />
            <label>First name: </label>
            <input type="text" name="firstName" placeholder="First name" value={this.state.firstName} onChange={this.handleFirstNameChange} />
            <label>Last name: </label>
            <input type="text" name="lastName" placeholder="Last name" value={this.state.lastName} onChange={this.handleLastNameChange} />
            <input type="submit" value="Add User" onClick={this.handleSubmit} />
        </div>
    )
}

}

1
  • 1
    You've a typo here: this.handlePasswordChange = this.handlePasswordChange(this);. It should be this.handlePasswordChange = this.handlePasswordChange.bind(this); Commented Oct 27, 2018 at 15:19

1 Answer 1

4

You are invoking handlePasswordChange in the constructor by writing handlePasswordChange(this). You want to bind it to this instead.

this.handlePasswordChange = this.handlePasswordChange.bind(this);
Sign up to request clarification or add additional context in comments.

1 Comment

thanks, this has helped me out too! I am new to react/JS and was trying to squeeze my way somehow with just one "handleChange" method :p Is it possible to use just one handleParamsChange method instead of binding respective handleChange methods? (maybe this qualifies as a separate question on SO x-" )

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.