使用下拉菜单反应过滤项目

React filter items with dropdown

本文关键字:过滤 项目 下拉菜单      更新时间:2023-09-26

我正在学习React,并希望使用下拉列表筛选列表。我差不多找到了,但我只能点击一次下拉列表,然后列表就会变空。我很确定这是因为我正在筛选列表,然后它会返回带有筛选项目的列表。但我不知道该如何改变。

演示

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')
);

因为第一次选择下拉菜单时会更新this.state.data。您应该使用this.props.data作为搜索源。您可以这样更改:

   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;
    });
    }

您的代码还有另一个考虑因素:唯一真正需要状态的组件是filterform。其他组件只需要道具。

这确实可以简化和减少您的代码。

  • 仅保持表单中的状态,并且只需要将选定的筛选器保持在该状态
  • 将筛选器选项+选定的筛选器传递到选项组件
  • 将整个datalist+选定的筛选器传递到您的列表组件

以下代码也完全符合您的要求(从73行代码减少到65行代码):

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')
    );