react-selectの基本的な使い方

はじめに

react-selectを使ってみたので基本的な使い方をまとめました。react-selectはReactで多機能なセレクトボックスを簡単に実装できるライブラリです。

実行環境:

  • PHP: 8.2.x
  • Laravel: 10.x
  • React: 18.2.0
  • react-select: 5.8.0

react-selectの導入

公式: React Select

インストール

npm i --save react-select

使い方

valuelabelキーを持ったオブジェクトリストを渡すだけです。例えば、ブログ記事の公開ステータスをセレクトボックスで選択したいとします。

import Select from 'react-select'

const statusOptions = [
  { value: 'public', label: '公開' },
  { value: 'private', label: '非公開' },
  { value: 'draft', label: '下書き' }
]

const MyComponent = () => (
  <Select options={statusOptions} />
)

optionsに渡す選択肢リストは、実際にはAPIレスポンスから受け取ったデータを使うことが多いと思います。例えば以下のようなusersデータはvaluelabelキーは持っていないためreact-selectで使えるように変換が必要です。

// APIレスポンスから受け取るusersデータの形式を想定
const users = [
  { id: 1, name: 'ユーザー1', email: 'user1@example.com'},
  { id: 2, name: 'ユーザー2', email: 'user2@example.com'},
  { id: 3, name: 'ユーザー3', email: 'user3@example.com'},
];

const options = users.map(user => ({
  value: user.id,
  label: user.name
}));

既存のキーを残したい場合は、元のオブジェクトをスプレッド構文(...)を使って新しいオブジェクトにコピーし、valuelabel を追加します。

const users = [
  { id: 1, name: 'ユーザー1', email: 'user1@example.com'},
  { id: 2, name: 'ユーザー2', email: 'user2@example.com'},
  { id: 3, name: 'ユーザー3', email: 'user3@example.com'},
];

const options = users.map(user => ({
  ...user,  // 既存の全てのキーと値を保持
  value: user.id,  // valueキーを追加
  label: user.name // labelキーを追加
}));

propsでカスタマイズ

選択肢の変更時イベント

onChange

<Select
  options={options}
  onChange={value => console.log(value)}
/>

選択されたオプションが変更されたときに実行されます。選択されたオプションを引数として受け取り、コンソールに出力して確認してみます。

{
  id: 1,
  name: "ユーザー1",
  email: "user1@example.com",
  value: 1,
  label: "ユーザー1",
}

options配列の中の選択されたオプションのuserオブジェクトを確認できました。

検索可能にする

isSearchable

<Select
  options={options}
  onChange={value => console.log(value)}
  isSearchable={true}
/>

検索値が見つからない時のメッセージ変更

noOptionsMessage

<Select
  options={options}
  onChange={value => console.log(value)}
  isSearchable={true}
  noOptionsMessage={() => "見つかりません。"}
/>

選択肢解除可能にする

isClearable

<Select
  options={options}
  onChange={value => console.log(value?.name)}
  isClearable={true}
/>

選択肢を解除するとonChangenullを受け取ります。そのため、オブジェクトのプロパティにアクセスする場合はエラーにならないよう、Null 合体演算子 (??)やオプション連鎖演算子 (?.) を使うなどハンドリングが必要です。

選択肢の表示をカスタム

getOptionLabel

<Select
  options={options}
  onChange={value => console.log(value?.name)}
  isSearchable={true}
  isClearable={true}
  getOptionLabel={option => option.label + ' : ' + option.email}
/>

デフォルトではlabelキーの値が表示されますが、「名前 : email」のような形式で表示することもできます。検索時にemailもヒットするようになります。

初期値をセットする

valueにオブジェクトを指定する。

// inertiaを使った例
import { useForm } from '@inertiajs/react';

const { data, setData, post } = useForm({
  user_id: 2, // 初期値を指定
});

...

<Select
  value={options.find(obj => obj.id === data.user_id)} // 一致するものを探してセット
  options={options}
  onChange={value => setData('user_id', value?.id)}
  isSearchable={true}
  isClearable={true}
  getOptionLabel={option => option.label + ' : ' + option.email}
/>

初期値はoptionsに渡した配列に含まれるオブジェクトで指定する必要があります。

options[0]のように特定の要素を指定したり、例のようにfindメソッドを使えばオブジェクトの特定のプロパティを検索して該当するオブジェクトを指定することもできます。

データ送信してみる

実際にSelectコンポーネントを使ってデータを送信してみます。以下の例ではInertia.jsを使っています。

import Select from 'react-select'
import { useForm } from '@inertiajs/react';

const MyComponent = () => {
  const users = [
    { id: 1, name: 'ユーザー1', email: 'user1@example.com'},
    { id: 2, name: 'ユーザー2', email: 'user2@example.com'},
    { id: 3, name: 'ユーザー3', email: 'user3@example.com'},
  ];

  const options = users.map(user => ({
    ...user,
    value: user.id,
    label: user.name
  }));

  const { data, setData, post } = useForm({
    user_id: 2,
  });

  function handleSubmit(e) {
    e.preventDefault()
    post('test');
  }

  return (
    <>
      <h2>テストフォーム</h2>
      <form onSubmit={handleSubmit}>
        <Select
          value={options.find(obj => obj.id === data.user_id)}
          options={options}
          onChange={value => setData('user_id', value?.id)}
          isClearable={true}
          getOptionLabel={option => option.label + ' : ' + option.email}
        />
        <button>送信</button>
      </form>
    </>
  );
}

export default MyComponent

さいごに

他にもたくさんのpropsが用意されており、カスタマイズすれば色々なパターンのセレクトボックスが作れそうです。実際に使いながら便利な機能を見つけたら随時更新していきます。

参考ソース

react-selectの公式ドキュメント:

Inertia公式 useForm使い方など:

Null 合体演算子 (??)、オプション連鎖演算子 (?.) について: