React select - 如何根据其他选择字段的选择选项过滤选择?

时间:2017-12-07 10:58:16

标签: javascript reactjs filter react-select

我正在使用react-select,我想在2个字段中显示匹配的城市对(某些起源只有某些目的地)。我一直在思考,并且无法根据原点选择字段中选取的内容来设置过滤目的地选择字段的方法。任何人有任何想法或任何tipps?谢谢!!

我的回复是一个包含对象的数组。每个物体都有(其中包括)原始城市和目的地城市:

...
{OriginDestinationLocations:{DestinationLocation:{CityName:'Orlando'}, OriginLocation:{CityName:'Miami'}}},
 {OriginDestinationLocations:{DestinationLocation:{CityName:'Orlando'}, OriginLocation:{CityName:'Chicago'}}},
 {OriginDestinationLocations:{DestinationLocation:{CityName:'Las Vegas'}, OriginLocation:{CityName:'Miami'}}}
....
// so here (pretending that would be the full list) when I pick Orlando as origin in the 1st selection field, I should only see Miami and Chicago in the second field.

class App extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      from:[],
      to:[]
    }
  }
componentDidMount() {
   cityPairs().then(response => {
        let from = [];
        let to = [];
    // here its wrong to separate destination and origin as origin needs to stay 'connected' to the matching destinations but I just don't know what else to do. if I push objects with always matching origins/destinations into 1 array, I was thinking it would create so many pair, that can't be right in terms of performance etc. or would that be the only way?
        for (var i = 0; i < response.length; i++) {
            from.push(response[i].DestinationLocation.CityName);
            to.push(response[i].OriginLocation.CityName);
        }
        this.setState({
            to: to,
            from: from
        })
    })
}

 handleChange(event) {
    this.setState({value: event.target.value});
 }
render(){
  return (
  <div>
      <Select
          name="form-field-name"
          value={this.state.value}
          onChange={this.handleChange}
          clearable={this.state.clearable}
          searchable={this.state.searchable}
          labelKey='name'
          valueKey='cityCode'
          options={this.state.to}
       />
  </div>
  )
}
}

- 添加部分:

 cityPairs().then(response => {
        this.setState({
            routes: response
                .reduce((dest, x) => Object.assign({}, dest, {
                  ...
                }), {})
        });
    }).then(res => {
        var result = [];
        var r = this.state.routes;
        for (var key in r) {
            result.push(key)
        }
        this.setState({
            originRoutes: result.map(x => ({
                name: x,
                value: x
            } ))
        })
    })

//as I believe  const routes  = this.state.routes[this.state.selected]; should be changed to

const originRoutes  = this.state.originRoutes[this.state.selected];
    const options = !originRoutes ? [] : originRoutes.map(x => ({
        name:  x,
        value: x
} ));

            <Select            
                onChange={this.onChange}
                options={this.state.originRoutes}
            />
            <Select                   
               onChange={this.onChange}
               options={options}
            />

1 个答案:

答案 0 :(得分:1)

此解决方案现在不包含的是一次又一次地发送请求。它最初只是从API加载数据。但我认为这就是API本身现在的工作方式。如果数据太大,应该更改。

class App extends React.Component {
    componentWillMount() {
        this.setState({
            routes: []
        });

        cityPairs().then(response => {
            // result is an object with a key of the origin name and a list of destination names
            this.setState({
                routes: response
                    .reduce((dest, x) => Object.assign({}, dest, {
                        // multiple lines at best :-D
                        [x.OriginLocation.CityName]: dest[x.OriginLocation.CityName] ? dest[x.OriginLocation.CityName].concat([x.DestinationLocation.CityName]) : [x.DestinationLocation.CityName]
                    }), {})
            });
        });
    }

    onChange(event) {
        this.setState({
            selected: event.value
        })
    }

    render() {
        const routes  = this.state.routes[this.state.selected];
        const options = !routes ? [] : routes.map(x => ({
            name:  x,
            value: x
        }));

        return(
            <div>
                <Select
                    ...
                    onChange={::this.onChange}
                    options={options}
                />
            </div>
        );
    }
}