mui/Autocompletの実装
投稿日: 2024年11月29日
以前にフロントエンド実装をやらせていただいた実務案件で、オートコンプリートの実装が要件になっていることがありました。
オートコンプリートって何? ?オイシイの?レベルから、なんとか実装しました(もう2ヶ月くらい前・・?)。印象には残っているもののあまり覚えていなかったので、復習も兼ねて備忘録としてまとめてみます。
どこかで見たことあるような機能だったので、オリアプではあんまりないかもしれないですが実務では使用すること多そうだなという印象でした。(シランケド)
入力フィールドに文字を入力すると、候補が自動的に絞り込まれて表示される機能です。
セレクトボックスが検索窓になっているような感じのやつです。
選択肢がズラッとでる。絞り込みも出来る。という便利な機能です。
material-uiを使用しました。
このライブラリを使うようにとか特に決まりはなくて、やりやすいように使い慣れているライブラリつかっていいしデザインもこだわりなしって感じでとてもやりやすかったのですが、ググったところmaterial-uiがヒットしてやりやすそうだなと感じたので使うことにしました。
全然関係ないんですけど、今まで既存のプロジェクト使って新たに書くコードは最低限に粘ってきたんですけど、今回さすがにブログ用のプロジェクト作ることにしましたw
material-uiとreact-hook-formをインストールします。
npm install @mui/material @emotion/react @emotion/stylednpm 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ができて感動しました。
今回は自分の復習のためでしたが、使う機会があれば参考にしてください。