mui/Autocompletの実装
投稿日: 2024年11月29日
以前にフロントエンド実装をやらせていただいた実務案件で、オートコンプリートの実装が要件になっていることがありました。
オートコンプリートって何? ?オイシイの?レベルから、なんとか実装しました(もう2ヶ月くらい前・・?)。印象には残っているもののあまり覚えていなかったので、復習も兼ねて備忘録としてまとめてみます。
どこかで見たことあるような機能だったので、オリアプではあんまりないかもしれないですが実務では使用すること多そうだなという印象でした。(シランケド)
入力フィールドに文字を入力すると、候補が自動的に絞り込まれて表示される機能です。
セレクトボックスが検索窓になっているような感じのやつです。
選択肢がズラッとでる。絞り込みも出来る。という便利な機能です。
material-uiを使用しました。
このライブラリを使うようにとか特に決まりはなくて、やりやすいように使い慣れているライブラリつかっていいしデザインもこだわりなしって感じでとてもやりやすかったのですが、ググったところmaterial-uiがヒットしてやりやすそうだなと感じたので使うことにしました。
全然関係ないんですけど、今まで既存のプロジェクト使って新たに書くコードは最低限に粘ってきたんですけど、今回さすがにブログ用のプロジェクト作ることにしましたw
material-uiとreact-hook-formをインストールします。
npm install @mui/material @emotion/react @emotion/styled
npm install react-hook-form
フォームの状態を管理するためにreact-hook-formも使用します。
"use client";
import { Autocomplete, TextField } from "@mui/material";
import { useForm, Controller } from "react-hook-form";
export const SampleAutocomplete: React.FC = () => {
const { control } = useForm<{ beer: { label: string; id: number } | null }>();
const options = [
{
label: "スーパードライ",
id: 1,
},
{
label: "プレモル",
id: 2,
},
{
label: "バドワイザー",
id: 3,
},
{
label: "エビス",
id: 4,
},
{
label: "一番搾り",
id: 5,
},
];
return (
<Controller
name="beer"
control={control}
defaultValue={null}
render={({ field }) => (
<Autocomplete
{...field}
options={options}
getOptionLabel={option => option.label}
renderInput={params => (
<TextField {...params} label="ビールの種類" required />
)}
onChange={(_, data) => field.onChange(data)}
isOptionEqualToValue={(option, value) => option.id === value?.id}
/>
)}
/>
);
};
import {Autocomplete,TextField} from '@mui/material';
import { useForm, Controller } from "react-hook-form";
オートコンプリートで必要なのは、@mui/materialからAutocompleteとTextField。
react-hook-formからuseFormと Controllerです。
const { control } = useForm<{ beer: { label: string; id: number } | null }>();
const options = [
{
label: "スーパードライ",
id: 1,
},
{
label: "プレモル",
id: 2,
},
{
label: "バドワイザー",
id: 3,
},
{
label: "エビス",
id: 4,
},
{
label: "一番搾り",
id: 5,
},
];
選択する項目は通常はAPIで取得したデータをlabelとid等、オートコンプリートで使える形に整形してから使用しますが、今回サンプルデータで実装したので直接定義しました。
私はスーパードライ派です
<Controller
name="beer"
control={control}
defaultValue={null}
name
:フォームのフィールド名。
control
:useForm
から取得したcontrol
オブジェクト
defaultValue
:初期値にnull
render={({ field }) => (
<Autocomplete
{...field}
options={options}
getOptionLabel={option => option.label}
renderInput={params => (
<TextField {...params} label="ビールの種類" required />
)}
onChange={(_, data) => field.onChange(data)}
isOptionEqualToValue={(option, value) => option.id === value?.id}
/>
)}
{...field}
:Controller
から渡されるfield
オブジェクトを展開し、value
やonChange
などのイベントハンドラをAutocomplete
に渡す。
これにより、React Hook FormがAutocomplete
の入力値を管理できる
options
:選択肢の配列。label
とid
を持つオブジェクトの配列として定義。
getOptionLabel
:各選択肢のlabel
を表示する関数。options
のlabel
を取得して表示
renderInput
:TextField
をレンダリングするための関数。params
にはAutocomplete
が必要とするプロパティが渡され、label="ビールの種類"
を指定。
onChange
:Autocomplete
の選択が変更されたときにReact Hook Form
のonChange
を呼び出し、フォームの値を更新。(_, data)
で受け取ったdata
が選択されたオプション。
isOptionEqualToValue
:選択肢と現在の値を比較するための関数。
オプションと現在の値が同じかどうかをid
で比較し、一致する場合に選択状態を正しく反映する。これにより、すでに選択済みの値がオプションとして認識され、リストが適切に絞り込まれる。
表示された内容から選択できて
検索もできます。
動画撮ったけど貼り方わからず。スクショですみませんw
この案件でmaterial-uiを初めて使いましたが、CSS苦手でも簡単にいい感じのUIができて感動しました。
今回は自分の復習のためでしたが、使う機会があれば参考にしてください。