useStateとuseMemoを使って実現した。
- useState
- フィルタ条件となる、店名、メニュー、評価の変数を管理する
- 入力欄の内容が変わった時、それを検知して値を更新・保持するように実装する
- useMemo
- useStateで管理している値に変更があった時「のみ」、フィルタを再計算する。余計な計算が走らなくて済む
- 再計算のトリガーとする値は、useMemoの記述の末尾に、[]内で指定
- useStateで管理している値に変更があった時「のみ」、フィルタを再計算する。余計な計算が走らなくて済む
index.tsx
const [nameFilter, setNameFilter] = useState("");
const [menuFilter, setMenuFilter] = useState("");
const [repeatFilter, setRepeatFilter] = useState<RepeatPreference | "">("");
const [modalIsOpen, setModalIsOpen] = useState(false);
const [selectedImage, setSelectedImage] = useState<string | null>(null);
const filteredRamen = useMemo(
() =>
ramenList.filter((ramen) => {
const matchesName = ramen.name
.toLowerCase()
.includes(nameFilter.toLowerCase());
const matchesMenu = ramen.menu
.toLowerCase()
.includes(menuFilter.toLowerCase());
const matchesRepeat = repeatFilter
? ramen.repeat === repeatFilter
: true;
return matchesName && matchesMenu && matchesRepeat;
}),
[ramenList, nameFilter, menuFilter, repeatFilter]
);
フィルタ条件を入力するテキストボックス例は以下。
index.tsx
<input
type="text"
value={nameFilter}
onChange={(e) => setNameFilter(e.target.value)}
className="block w-full p-1 border rounded shadow-sm focus:ring-2 focus:ring-blue-500"
placeholder="店名"
/>