Home

react-selectのフィルターを
カスタマイズ

update: 2019-05-20

react

お馴染みmaterial-uiのAutocompleteの検索フィルターをカスタマイズしたい。具体的には人名を漢字でもひらがなでもマッチさせたい。デモページからわかる通りAutocompleteというコンポーネントが用意されているわけではなく、コアの部分は他のライブライに委ねてUI部分のみカスタマイズしている。(ということで、本記事ではmaterial-uiについては触れません🙄)3つの人気ライブラリをそれぞれ使ったサンプルが用意されているが、自分はGitHubのスター数が一番多いreact-selectを選択した。

react-selectの基本的な使い方

使用時のバージョンは2.4.3。下記例はREADMEにもあるサンプルだが、options Propに[{value:foo,label:bar},...]形式で選択対象を渡している。

  • label:リストに表示する値、入力項目の検索対象
  • value:同一か判定する識別子。同じvalueの項目は複数選択できない。

また、onChangeのcallback引数には選択されているoptionsがそのまま配列で渡される。

import React from 'react';
import Select from 'react-select';

const options = [
  { value: 'chocolate', label: 'Chocolate' },
  { value: 'strawberry', label: 'Strawberry' },
  { value: 'vanilla', label: 'Vanilla' }
];

class App extends React.Component {
  state = {
    selectedOption: null,
  }
  handleChange = (selectedOption) => {
    this.setState({ selectedOption });
    console.log(`Option selected:`, selectedOption);
  }
  render() {
    const { selectedOption } = this.state;

    return (
      <Select
        value={selectedOption}
        onChange={this.handleChange}
        options={options}
      />
    );
  }
}

これが基本的な使い方だが、例えばoptionsに下記のようなデータを渡したいケースがある。

const options = [
  { id:1, kanji: '田中太郎', hiragana: 'たなかたろう' },
  { id:2, kanji: '鈴木一郎', hiragana: 'すずきいちろう' },
];

kanjiをlabelに置き換えると表示項目に対しては問題ないが、検索はkanji,hiragana両方に対して行いたい。そんなときの対策を紹介する。といっても記事React-Select with custom label and custom searchをめちゃくちゃ参考にさせていただいた。

検索フィルターをカスタマイズ

追加するPropは下記3つ

getOptionLabel

labelとして扱いたい値を定義する。コールバック引数にはoptions配列の各値が渡される。

getOptionValue

上記と同様にvalueを定義する。

filterOption

検索方法を定義できる。callbackの第一引数はoptionの値がそのまま入ってくるわけではないので注意。

const customFilter = (
    option: {
      data: {
        id: number
        kanji: string
        hiragana: string
      }
    },
    searchText: string
  ) => {
    return (
      option.data.kanji.replace(' ', '').includes(searchText) ||
      option.data.hiragana.replace(' ', '').includes(searchText)
    )
  }

これで入力値がひらがなでも漢字でも検索できるようになる。

リスト表示の高速化

リストが多すぎると、すごく重たくなる。そこでリストを表示するコンポーネントとしてreact-virtualizedを食わせてあげるとスクロールがスムーズになる。material-uiと組み合わせた実装例もあった。