Marcus Junius Brutus Marcus Junius Brutus - 1 month ago 7
React JSX Question

why does ReactJS suppress changes in <input> elements but not in e.g. <select> elements

Here's a SSCCE to illustrate my question:

const React = require('react');

const App = React.createClass({
getInitialState: function() {
return {
text: 'foo',
selection: 'apples'
};
}
, render: function() {
return (
<div>
<div>
<input type='text' value={this.state.text}/>
</div>
<select>
<option value='bananas' selected={this.state.selection==='bananas'}>bananas</option>
<option value='apples' selected={this.state.selection==='apples'} >apples </option>
<option value='onions' selected={this.state.selection==='onions'} >onions </option>
</select>
</div>
);
}
});


The above React component when rendered, displays (unsurprisingly) the below view:

enter image description here

The model is taken into account as expected.

When one tries to type into the
<input>
element nothing happens. The explanation is that ReactJS uses one way flow and you have to add
onchange
listeners to update the model etc. That's fine.

What I don't get is why ReactJS prevents the
<input>
element from changing and forces it to always reflect the model value that flowed down to it, whereas at the same time it allows me to change the
<select>
element:

enter image description here

enter image description here

Apparently my mental model is lacking. What am I missing ?

Answer

What you have here is a controlled <input> element and an uncontrolled <select> element. See controlled components

Its possible to create an uncontrolled text input by not specifying the value prop.

And its possible to create a controlled select element by specifying the value prop.

<select value={this.state.value}>
  <option value="bannanas">bananas</option>
  <option value="apples">apples</option>
  <option value="onions">onions</option>
</select>

There is documentation explaining specifically this. See here