Angular 1.X has ng-options for the choices in a select dropdown, each item being an object. In plain HTML, the value of an option can only be a string. When you select one option in Angular, you can see the actual selected object while in plain html, you can only get that string value.
How do you do the equivalent of that in React (+Redux)?
I came up with a solution that does not use JSON.stringify / parse for the value of the select React element nor does it use the index of the array of choice objects as the value.
The example is a simple select dropdown for a person's gender -- either male or female. Each of those choices is an actual object with id, text, and value properties. Here is the code:
MySelect component
import React, { Component } from 'react';
class MySelect extends Component {
onGenderChange = (event) => {
// Add the second argument -- the data -- and pass it along
// to parent component's onChange function
const data = { options: this.props.options };
this.props.onGenderChange(event, data);
}
render() {
const { options, selectedOption } = this.props;
// Goes through the array of option objects and create an <option> element for each
const selectOptions = options.map(
option => <option key={option.id} value={option.value}>{option.text}</option>
);
// Note that if the selectedOption is not given (i.e. is null),
// we assign a default value being the first option provided
return (
<select
value={(selectedOption && selectedOption.value) || options[0].value}
onChange={this.onGenderChange}
>
{selectOptions}
</select>
);
}
}
App component that uses MySelect
import _ from 'lodash';
import React, { Component } from 'react';
class App extends Component {
state = {
selected: null
}
onGenderChange = (event, data) => {
// The value of the selected option
console.log(event.target.value);
// The object for the selected option
const selectedOption = _.find(data.options, { value: parseInt(event.target.value, 10) });
console.log(selectedOption);
this.setState({
selected: selectedOption
});
}
render() {
const options = [
{
id: 1,
text: 'male',
value: 123456
},
{
id: 2,
text: 'female',
value: 654321
}
];
return (
<div>
<label>Select a Gender:</label>
<MySelect
options={options}
selectedOption={this.state.selected}
onGenderChange={this.onGenderChange}
/>
</div>
);
}
}
Lodash is used to look up the choice object in the array of choice objects inside the onGenderChange
function in the App component. Note that the onChange passed to the MySelect
component requires two arguments -- an extra data argument is added in order to be able to access the choice objects ("options"). With that, you can just set the state (or call an action creator if using Redux) with the choice object for the selected option.