0

Why am I unable to type into my form with the following code? I've correctly set my form values to the data in the state but I'm unable to type into them.

Component is changing an uncontrolled input of type email 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.

construtor()
{
  super(props);
  this.state= { user: {} }
  this.onChange = this.onChange.bind(this);
}

componentWillReceiveProps(nextProps)
{
    this.state.user !== nextProps.user &&
        this.setState({ user: nextProps.user });  
}

onChange(e)
{
    let newUser = this.state.user;
    newUser[e.target.name] = e.target.value;
    this.setState({ user: newUser });
}

<form>
    <input name="email" type="email" className="form-control" value={this.state.user.email} onChange={this.onChange}/>
    <input name="first_name" type="text" className="form-control" value={this.state.user.first_name} onChange={this.onChange}/>
</form>
anonym
  • 4,460
  • 12
  • 45
  • 75
  • you are mutating the state in onChange function. – Prakash Sharma Jul 31 '17 at 11:51
  • Would you explain further what mutating in onChange means and what's the solution? Thanks. – anonym Jul 31 '17 at 11:53
  • I think it should be `onChange(e) { let newUser = this.state.user; newUser[e.target.name] = e.target.value; this.setState({ user: newUser }); }` – Daniel Andrei Jul 31 '17 at 11:54
  • Thanks for the suggest, Daniel. That was a small blunder in the question. Unfortunately, despite changing to newUser[e.target.value], the same behavior still persists. – anonym Jul 31 '17 at 12:01
  • Technically, you need to have an initial value for `email` and `first_name` set to empty string in the constructor method. and in the onChange handler, you should do this, onChange({target: {name, value}}) { this.setState({...this.state.users, user: { [name]: value}}) }. For handling state in React, check out [this](https://medium.com/@housecor/handling-state-in-react-four-immutable-approaches-to-consider-d1f5c00249d5) – Rowland Jul 31 '17 at 13:33

1 Answers1

1

Because default value of user variable is {} and this.state.user.email and this.state.user.first_name will be undefined initially, and since you are initially assigning:

value = {this.state.user.email or undefined} ==> this.state.user.email is undefined

So value property will have undefined and input field will become uncontrolled, once you enter any value after that it will become controlled, because after that user object will have the keys, that why you are getting the error:

Component is changing an uncontrolled input of type email to be controlled.

Solution:

1- Either define the user in constructor like this:

this.state= { user: {email: '', first_name: ''} }

2- Or write the input field like this (put default value as "" to handle undefined case):

<form>
    <input value={this.state.user.email || ""} ..../>
    <input value={this.state.user.first_name || ""} ..../>
</form>

Suggestion:

Do not mutate the state values directly so before doing any change first copy the state object then do the changes, and use setState to update the state value.

Check this answer: What is the most efficient way to deep clone an object in JavaScript?

Mayank Shukla
  • 100,735
  • 18
  • 158
  • 142
  • Thanks for your time, Shukla. The code seems alright but for some reason, the error message doesn't go away and I'm unable to update the fields. It could be some mistake from my side; I'll keep trying and let you know how it goes. – anonym Aug 01 '17 at 07:21
  • Appreciate it. – anonym Aug 01 '17 at 07:28