検索用のコンポーネント
検索用のコンポーネントに本のデータを渡して、カテゴリーと出版社データから検索して絞り込めるようにする。
参考にした方法では、検索結果の状態を保存しているので、親コンポーネントの変更が反映されなかった。なので検索条件を保存して、検索結果を保存しないことにした。
カテゴリー、出版社、検索語句で絞り込む。以下のようなjsonオブジェクトをbookとして配列で渡される。
カテゴリーはカンマで区切られているので分割してから検索する。検索語句は全体に検索する。
[
{
"Asin": "B0CSYLW8ML",
"URL": "https://www.amazon.co.jp/dp/B0CSYLW8ML?tag=99hatena-22&linkCode=ogi&th=1&psc=1",
"ImageURL": "https://m.media-amazon.com/images/I/51hLyvAAPCL._SL500_.jpg",
"Publisher": "KADOKAWA",
"Contributor": "日月 ネコ(著)",
"Booktype": "Kindle版",
"Title": "理想のヒモ生活(19) (角川コミックス・エース)",
"Price": 733,
"Category": "コミック,少年マンガ,カドカワコミックス・エース",
"Points": 367,
"Day": 20240202
},
{
"Asin": "B0CQXW5KBP",
"URL": "https://www.amazon.co.jp/dp/B0CQXW5KBP?tag=99hatena-22&linkCode=ogi&th=1&psc=1",
"ImageURL": "https://m.media-amazon.com/images/I/515CWzfPjNL._SL500_.jpg",
"Publisher": "集英社",
"Contributor": "タカヒロ(著)",
"Booktype": "Kindle版",
"Title": "魔都精兵のスレイブ 15 (ジャンプコミックスDIGITAL)",
"Price": 502,
"Category": "コミック,少年マンガ,ジャンプコミックス",
"Points": 133,
"Day": 20240202
},
]
useStateは検索条件を保存する。adultの初期状態はfalseにして、toggle switchでクリックするたびに切り替える。
const [adult, setAdult] = useState(false);
if (!adult) {
const cate = post.Category.split(",");
a = cate.every(item => item !== "アダルト" && item !== "HOTW_Test_アダルト");
}
<input type="checkbox" id="switch" checked={adult} onChange={() => setAdult(prev => !prev)} />
filter処理を繰り返さないように。複数の検索条件をまとめて&&で複数条件で検索できるようにした。
const [adult, setAdult] = useState(false);
const [inputValue, setInputValue] = useState("");
const [selCate, setSelCate] = useState("");
const [selPub, setSelPub] = useState("");
// フィルタリング処理
const filteredList = book.filter((post) => {
let a = true, c = true, p = true, w = true;
// アダルトカテゴリを除外
if (!adult) {
const cate = post.Category.split(",");
a = cate.every(item => item !== "アダルト" && item !== "HOTW_Test_アダルト");
}
// カテゴリー絞り込み
if (selCate !== "") {
const cate = post.Category.split(",");
c = selCate.some(item => cate.includes(item));
}
// 出版社絞り込み
if (selPub !== "") {
const pub = post.Publisher.split(",");
p = selPub.some(item => pub.includes(item));
}
// フリーキーワード検索
if (inputValue !== "") {
w = Object.values(post).some(item =>
item &&
item.toString().toUpperCase().includes(inputValue.toUpperCase())
);
}
return a && c && p && w;
});
// カテゴリー選択
const selectCategory = (category) => {
setSelCate(category);
};
// 出版社選択
const selectPublisher = (publisher) => {
setSelPub(publisher);
};
// リセット
const reset = () => {
setSelPub("");
setSelCate("");
setInputValue("");
};
// 入力変更ハンドラ
const handleInputChange = (e) => {
setInputValue(e.target.value);
};
return (
<>
{/* カテゴリー選択ボタン */}
<div>
<h4>クリックしてカテゴリーと出版社で絞り込みが可能</h4>
<p>
カテゴリー:アダルト許可
<input type="checkbox" id="switch" checked={adult} onChange={() => setAdult(prev => !prev)} />
<button className="categorybutton" onClick={reset}>全て</button>
{categories.map((category) => (
<button key={category} className="categorybutton" onClick={() => selectCategory(category)}>
{category}
</button>
))}
</p>
{/* 出版社選択ボタン */}
<details>
<summary><strong>クリックして出版社選択ボタンの表示</strong></summary>
<p>
出版社:
<button className="categorybutton" onClick={reset}>全て</button>
{publishers.map((publisher) => (
<button key={publisher} className="categorybutton" onClick={() => selectPublisher(publisher)}>
{publisher}
</button>
))}
</p>
</details>
</div>
{/* フリーキーワード検索フォーム */}
<div>
<h4>フリーキーワード検索</h4>
<input type="text" value={inputValue} onChange={handleInputChange} />
</div>
{/* 結果の表示 */}
<Paginate itemsPerPage={10} items={filteredList} />
</>
);
この記事を参考にした