novaline novaline - 1 month ago 4x
React JSX Question

React controlled component input value with empty string

I wrote a demo below for test

controlled component
feature. But It seems there is a bug.

class TestComponent extends React.Component{
constructor() {
this.state = {value: 'beef'};
this.handleValueChange = this.handleValueChange.bind(this);

handleValueChange(e) {
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>
<div><input type='text' defaultValue={this.state.value} onChange={this.handleValueChange}/></div>

<TestComponent />,

<script src=""></script>
<script src=""></script>

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

The second one
with empty string value property. when I type something, it call
function, but finally, it always give me one character.

It's weird.

I add a
, compare with
, my head is mess up..


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}/>

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:


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! :)