I'm learning React and wanted to filter a list using a dropdown. I've almost got it but I can only click the drop down once and then the list will go empty. I'm pretty sure it's because I'm filtering the list and then it returns the list with the filtered items. But I'm not sure how to change that.
demo
var filterData = [
{ name: 'Matthew', sex: 'male' },
{ name: 'Amanda', sex: 'female' }
];
var FilterForm = React.createClass({
getInitialState: function() {
return {
data: this.props.data,
sex: ''
}
},
handleChange: function(val) {
// problem is here
var filteredData = this.state.data.filter(function(item) {
return item.sex === val;
});
this.setState({sex: val});
this.setState({data: filteredData});
console.log(filteredData);
},
render: function() {
return (
<div className="filter-form">
<h1>Filter Form</h1>
<FilterOptions data={this.state.data} changeOption={this.handleChange} />
<FilterItems data={this.state.data} />
</div>
);
}
});
var FilterOptions = React.createClass({
getInitialState: function() {
return {
data: this.props.data,
sex: ''
}
},
handleChange: function(e) {
var val = e.target.value;
this.setState({bender: val});
this.props.changeOption(val);
},
render: function() {
return (
<select id="sex" value={this.state.sex} onChange={this.handleChange}>
<option value=""></option>
<option value="male">male</option>
<option value="female">female</option>
</select>
);
}
});
var FilterItems = React.createClass({
getInitialState: function() {
return {
data: this.props.data
}
},
render: function() {
return (
<div className="filter-item">
{this.props.data.map(function(item) {
return (
<div>{item.name}</div>
);
})}
</div>
);
}
});
React.render(
<FilterForm data={filterData} />,
document.getElementById('app')
);
To create a dropdown select in React, use the react-select library. The react-select library has features dynamic search/filter, async option loading, accessibility, and fast render times. In addition, it has a flexible and beautiful Select Input control for ReactJS with multi-select, autocomplete, and ajax support.
Here is an example of modifying App.js to display a dropdown menu of aquatic animals: Add an array for aquaticCreatures and use the Select component provided by React Select: You will notice three things: You must import the Select component from react-select.
However, there may be situations where a select menu can benefit from additional user experience niceties, like allowing a user to filter available choices. React Select is a highly configurable select menu library for React that features dynamic search and filter. It also supports async option loading, accessibility, and fast render times.
React Select is a highly configurable select menu library for React that features dynamic search and filter. It also supports async option loading, accessibility, and fast render times. In this tutorial, you will add React Select to a project.
Because your this.state.data
is updated when you selected the drop-down at the first time. You should use this.props.data
as the searching source You can change like this :
handleChange: function(val) {
this.setState({sex: val});
var filteredData;
if(val == ""){
filteredData = this.props.data;
}else{
filteredData = this.props.data.filter(function(item) {
return item.sex === val;
});
}
There another consideration for your code as well: the only component that really needs state is the filterform. The other components only need props.
This can really simplify and reduce your code.
The following code also does exactly what you want (and reduces from 73 to 65 lines of code):
var data = [
{ name: 'Matthew', sex: 'male' },
{ name: 'Amanda', sex: 'female' }
];
var FilterForm = React.createClass({
getInitialState: function() {
return {
sex: ''
}
},
handleChange: function(val) {
this.setState({sex: val});
console.log(val);
},
render: function() {
// create list of options from input data (based on sex)
var optionsArray=this.props.data.map((item) => { return item.sex });
optionsArray.unshift("");
return (
<div className="filter-form">
<h1>Filter Form</h1>
<FilterOptions options={optionsArray} selected={this.state.sex} changeOption={this.handleChange} />
<FilterItems data={this.props.data} filter={this.state.sex} />
</div>
);
}
});
var FilterOptions = React.createClass({
handleChange: function(e) {
var val = e.target.value;
this.props.changeOption(val);
},
render: function() {
var selectedOption = this.props.selected;
return (
<select id="sex" value={selectedOption} onChange={this.handleChange}>
{this.props.options.map(option => {
return <option key={option} value={option} selected={(option.value == selectedOption)}>{option}</option>;
})}
</select>
);
}
});
var FilterItems = React.createClass({
render: function() {
var filter = this.props.filter;
var filteredData = this.props.data.filter((item) => {
return (!filter || item.sex == filter)
});
return (
<div className="filter-item">
{filteredData.map(function(item) {
return (
<div>{item.name}</div>
);
})}
</div>
);
}
});
React.render(
<FilterForm data={data} />,
document.getElementById('app')
);
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With