使用下拉列表反映过滤器项目

时间:2015-11-09 16:20:10

标签: javascript reactjs

我正在学习React并希望使用下拉列表过滤列表。我几乎得到了它但我只能点击下拉列表然后列表将变空。我很确定它是因为我过滤了列表然后它返回带有过滤项的列表。但我不确定如何改变它。

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

2 个答案:

答案 0 :(得分:8)

因为您在第一次选择下拉列表时更新了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;
    });
    }

答案 1 :(得分:5)

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

这可以真正简化和减少您的代码。

  • 仅保留状态,您只需将所选过滤器保持在状态
  • 将过滤器选项+所选过滤器传递给您的选项组件
  • 将整个datalist + selected过滤器传递给列表组件。

以下代码也完全符合您的要求(并减少了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')
    );