2
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

記事投稿キャンペーン 「2024年!初アウトプットをしよう」

【React+MUI】検索ボックス実装の例

Last updated at Posted at 2024-01-14

まずAutocompleteを使えないか検討してみる。

こんなの↓
image.png
AutoComplete(MUI公式)

MUIはそれぞれのライブラリに豊富なサンプルコードがあるので、そちらを参考にしながら実装してみましょう。

Autocompleteが使えそうにない場合

例えば

  • 入力フォームとリストを横並びにしたい
  • 入力フォームに文字を入力してもリストはずっと表示しておきたい
    など
    image.png

作りたいアプリの仕様上自作する必要がある時、MUIのTextFieldListを使って実装ができます。

参考コード

SearchBoxDemo.js
import {
 Avatar,
  Box,
  Grid,
  List,
  ListItem,
  ListItemAvatar,
  ListItemText,
  TextField,
} from "@mui/material";
import { nameListData } from "../data/NameSample";
import { useState } from "react";

export function SearchBoxDemo() {
  const [nameList, setNameList] = useState(nameListData);

  const filteringName = (inputValue) => {
    if (inputValue) {
      const filteredNames = nameListData.filter((name) =>
        name.toLowerCase().includes(inputValue.toLowerCase())
      );
      setNameList(filteredNames);
    } else {
      setNameList(nameListData);
    }
  };

  return (
    <Box sx={{ display: "flex", justifyContent: "center" }}>
      <Grid container spacing={2}>
        <Grid item xs={2}>
          <Box sx={{ height: "50vh", padding: "15px" }}>
            <TextField
              margin="normal"
              fullWidth
              onChange={(e) => filteringName(e.currentTarget.value)}
            />
          </Box>
        </Grid>
        <Grid item xs={2}>
          <Box sx={{ height: "30vh", padding: "15px", overflow: "auto" }}>
            <List>
              {nameList.length > 0 ? (
                nameList.map((name) => (
                  <ListItem key={name}>
                    <ListItemAvatar>
                      <Avatar>{name.substr(0, 1)}</Avatar>
                    </ListItemAvatar>
                    <ListItemText>{name}</ListItemText>
                  </ListItem>
                ))
              ) : (
                <ListItem>
                  <ListItemText>検索結果が見つかりませんでした</ListItemText>
                </ListItem>
              )}
            </List>
          </Box>
        </Grid>
      </Grid>
    </Box>
  );
}
nameListData.js
export const nameListData = [
  "John Smith",
  "Emily Johnson",
  "Michael Williams",
  "Olivia Brown",
  "William Jones",
  "Ava Davis",
  "James Wilson",
  "Emma Taylor",
  "Alexander Martinez",
  "Sophia Anderson",
  "Daniel Thomas",
  "Chloe Garcia",
  "Matthew Hernandez",
  "Grace Moore",
  "David Martin",
  "Ella Rodriguez",
  "Andrew Miller",
  "Madison White",
  "Joseph Lee",
  "Abigail Harris",
  "Nicholas King",
  "Samantha Clark",
  "Tyler Lewis",
  "Natalie Hall",
  "Christopher Young",
  "Lily Allen",
  "Ryan Scott",
  "Hannah Green",
  "Brandon Walker",
  "Avery Perez",
  "Justin Lopes",
  "Victoria Hill",
  "Ethan Baker",
  "Zoe Carter",
  "Jonathan Nguyen",
  "Mia Rivera",
  "Christian Ward",
  "Isabella Cooper",
  "Dylan Gonzales",
  "Aria Wright",
  "Gabriel Torres",
  "Sofia Murphy",
  "Benjamin Powell",
  "Aaliyah Butler",
  "Samuel Long",
  "Hailey Foster",
  "Jackson Russell",
  "Penelope Perry",
];

解説

TextFieldにテキストが入力されたらonChangeイベントが発火し、該当する要素をフィルターする。

今回の例はあいまい検索をしていますが、前方一致、後方一致、完全一致など実装に合わせて適宜.filter()の中の条件を変えて下さい。

また、テキストが何も入力されない場合は初期値をセットしてます。

SearchBoxDemo.js
  const filteringName = (inputValue) => {
    if (inputValue) {
      const filteredNames = nameListData.filter((name) =>
        name.toLowerCase().includes(inputValue.toLowerCase())
      );
      setNameList(filteredNames);
    } else {
      setNameList(nameListData);
    }
  };

フィルターした結果条件と一致する要素がなかった場合は検索結果が見つからないというメッセージを表示。

SearchBoxDemo.js
{nameList.length > 0 ? (
    nameList.map((name) => (
      <ListItem key={name}>
        <ListItemAvatar>
          <Avatar>{name.substr(0, 1)}</Avatar>
        </ListItemAvatar>
        <ListItemText>{name}</ListItemText>
      </ListItem>
    ))
  ) : (
    <ListItem>
      <ListItemText>検索結果が見つかりませんでした</ListItemText>
    </ListItem>
  )}

実際の動作
検索ボックス.mp4.gif

注意点

今回リストの中身が50件程ということもあり問題なく動作しています。
しかしリストの件数が100件、1000件…と増える場合やmapでリターンする内容がもっとリッチな場合は、onChangeをただ走らせているだけだとパフォーマンスに影響が出る恐れがあります。

onChangeのパフォーマンス改善案

2
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?