Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

React controlled component input value with empty string

I wrote a demo below for the test React controlled component input feature. But It seems there is a bug.

class TestComponent extends React.Component{
  constructor() {
    super();
    this.state = {value: 'beef'};
    this.handleValueChange = this.handleValueChange.bind(this);
  }
  
  handleValueChange(e) {
    this.setState({value: e.target.value});
  }
  render() {
    return <div>
      <div><input type='text' value={'hello world'} onChange={this.handleValueChange}/></div>
      <div><input type='text' value={''} onChange={this.handleValueChange}/></div>
      <div><input type='text' value={this.state.value} onChange={this.handleValueChange}/></div>
      <div><input type='text' value={null} onChange={this.handleValueChange}/></div>
      <div><input type='text' value={undefined} onChange={this.handleValueChange}/></div>
      <hr/>  
      <div><input type='text' defaultValue={this.state.value} onChange={this.handleValueChange}/></div>
      <p>{this.state.value}</p>
    </div>
  }
}

ReactDOM.render(
  <TestComponent />,
  document.body
)
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>

The first one input with specifying string value property. when I type something, call handleValueChange function, and the result is hello world + your type thing's first character.

The second one input with empty string value property. when I type something, it calls handleValueChange function, but finally, it always gives me one character.

It's weird.

updated! I add a input with defaultValue, compare with value={this.state.value}, my head is mess up..

like image 307
slideshowp2 Avatar asked Apr 25 '26 06:04

slideshowp2


1 Answers

As mentioned in a comment below your question: remove value={''} since this will empty the input everytime it's rendered.

From the react docs, the correct way to do it is

return <div>
  <input type='text' value={this.state.value} onChange={this.handleValueChange}/>
  <p>{this.state.value}</p>
</div>

This way whenever you type something in the input-area, you'll update the value set in state.

If you want to render the component with a value set in state, you could use:

getInitialState() {
  return { value: 'Your default value'}
}

Or, as already suggested, use defaultValue.

Read more here: https://facebook.github.io/react/docs/forms.html


Update:

According to your updated question, I think you'll have to understand what setting a value during render function actually does. Whenever you set a value during render function, you'll "lock" the input field to be that specific value. Meaning the user input will have no effect on the rendered element. From the docs: "User input will have no effect on the rendered element because React has declared the value".

To solve this problem, you'll have to set the value to be something you can change dynamically, in your case that will be value or this.state.value. Like you've done in your third example:

<input type='text' value={this.state.value} onChange={this.handleValueChange}/>

This way React accept the value provided by the user input and will then update the value of the component thereafter.

I still think the docs specifies this pretty clearly, and I think you should read the provided documentation in my original answer.


Update 2

To clearify the part with controlled and uncontrolled components little bit:

A controlled component is a component that has a value property assigned, and will reflect the value from the user input (the value prop).

While an uncontrolled component does not have any value property assigned, and will NOT reflect the value from the user input (since it does not provide any value prop). But if you want to instantiate an uncontrolled component with a value, you should use defaultValue.

In your case (since you try to use a CONTROLLED component) this means that you should NOT use defaultValue, and stick with a correct implementation of a controlled component. That is an implementation using value={this.state.value}.

Again I recommend reading the docs provided. It's actually not that difficult if you manage to understand the docs.

Hope this clearifies some of you problems! :)

like image 198
chrisv Avatar answered Apr 27 '26 20:04

chrisv