Overview
- react-selectで選択肢をカスタムするには
formatOptionLabel
属性を使用する - 「ドロップダウンメニューの選択肢」と「選択後の値」を出し分けるには
meta
引数を使用する
はじめに
react-select は、Reactでセレクトボックスを実装するためのライブラリです。
本記事では、ドロップダウンメニューの選択肢表示をカスタマイズする方法を紹介します。
選択肢をカスタマイズする
src/components/CustomSelect.tsx
import Select from 'react-select';
interface Option {
role: 'admin' | 'none';
name: string;
}
const options: Option[] = [
{ role: 'admin', name: 'John' },
{ role: 'none', name: 'Alice' },
];
const CustomSelect = () => {
const FormatOptionLabel = (data: Option) => {
const isAdmin = data.role === 'admin';
return (
<div style={{ display: 'flex', gap: '8px', alignItems: 'center' }}>
<div style={{ color: isAdmin ? 'blue' : 'black', width: '60px' }}>{isAdmin ? '管理者' : '一般'}</div>
<div style={{ color: 'black' }}>{data.name}</div>
</div>
);
};
return (
<Select
options={options}
formatOptionLabel={(data) => FormatOptionLabel(data)}
getOptionValue={(option) => option.name} // 識別子
/>
);
};
export default CustomSelect;
選択肢の型 & 選択肢を定義する
任意の型構造で大丈夫です。
interface Option {
role: 'admin' | 'none';
name: string;
}
const options: Option[] = [
{ role: 'admin', name: 'John' },
{ role: 'none', name: 'Alice' },
];
FormatOptionLabel
関数を作成する
今回は、管理者ユーザーのみ色を変更するようにしました。
詳しくは後述しますが、全てのkey
を使用する必要はありません。
const FormatOptionLabel = (data: Option) => {
const isAdmin = data.role === 'admin';
return (
<div style={{ display: 'flex', gap: '8px', alignItems: 'center' }}>
<div style={{ color: isAdmin ? 'blue' : 'black', width: '60px' }}>{isAdmin ? '管理者' : '一般'}</div>
<div style={{ color: 'black' }}>{data.name}</div>
</div>
);
};
Select
にプロパティを渡す
return (
<Select
options={options}
formatOptionLabel={(data) => FormatOptionLabel(data)}
getOptionValue={(option) => option.name} // 識別子
/>
)
選択後の表示をカスタマイズする
import Select, { FormatOptionLabelMeta, StylesConfig } from 'react-select';
interface Option {
role: 'admin' | 'none';
name: string;
}
const options: Option[] = [
{ role: 'admin', name: 'John' },
{ role: 'none', name: 'Alice' },
];
const customStyles: StylesConfig<Option, false> = {
control: (provided) => ({
...provided,
width: '200px', // コントロール(選択エリア)の幅を設定
}),
};
const CustomSelect = () => {
const FormatOptionLabel = (data: Option, meta: FormatOptionLabelMeta<Option>) => {
const isAdmin = data.role === 'admin';
return meta.context === 'menu' ? (
<div style={{ display: 'flex', gap: '8px', alignItems: 'center' }}>
<div style={{ color: isAdmin ? 'blue' : 'black', width: '60px' }}>{isAdmin ? '管理者' : '一般'}</div>
<div style={{ color: 'black' }}>{data.name}</div>
</div>
) : (
<div style={{ color: 'black' }}>{data.name}</div>
);
};
return <Select options={options} formatOptionLabel={FormatOptionLabel} getOptionValue={(option) => option.name} styles={customStyles} />;
};
export default CustomSelect;
meta
を使用し、表示の出し分けを行う
先ほどとの違いはmeta
を使用し、表示を出し分けている点です。
meta
は'menu'
と'value'
の2つの値を持ちます。
'menu'
はドロップダウンメニューに対して、
'value'
は選択後の表示に対して発火します。
1 | 2 |
---|---|
![]() |
![]() |
選択肢ではrole が表示されている |
選択後は名前のみ表示 |
return meta.context === 'menu' ? (
<div style={{ display: 'flex', gap: '8px', alignItems: 'center' }}>
<div style={{ color: isAdmin ? 'blue' : 'black', width: '60px' }}>{isAdmin ? '管理者' : '一般'}</div>
<div style={{ color: 'black' }}>{data.name}</div>
</div>
) : (
<div style={{ color: 'black' }}>{data.name}</div>
);
customStyle
を適用
menu
/ value
で表示を出し分けると、以下画像1のようなレイアウト崩れが発生します。
customStyle
を適用することで、柔軟なレイアウトを実現可能です。
1 | 2 |
---|---|
![]() |
![]() |
menu のレイアウト崩れ |
コンパクトなセレクトボックス |
const customStyles: StylesConfig<Option, false> = {
control: (provided) => ({
...provided,
width: '200px', // コントロール(選択エリア)の幅を設定
}),
};
// ~~
return <Select
options={options}
formatOptionLabel={FormatOptionLabel}
getOptionValue={(option) => option.name}
styles={customStyles} />;
menu
も設定する場合
const customStyles: StylesConfig<Option, false> = {
menu: (provided) => ({
...provided,
width: '200px', // メニューの幅を設定
}),
control: (provided) => ({
...provided,
width: '100px', // コントロール(選択エリア)の幅を設定
}),
};
おわりに
react-select
は(公式の情報が弱い節はありますが)とても便利なライブラリです。
ぜひ使ってみてください!