🐕

React(GatsbyJS)でtagフィルタリング画面実装

2021/01/04に公開

1. 概要

このブログポートフォリオページ(/portfolio/)(Closeしました)では、過去作成したポートフォリオをリスト形式で一覧表示していますが、これを採用した技術スタック毎に tag で絞り込む機能を実装しました。(以下右の図が絞り込み後の画面)

タグフィルタ画面

2. 技術構成(Airtable 側の設定)

基本情報は、tag の情報も含めて Airtable で管理しています。Airtable のフィールドタイプは、MultipleSelect に指定します。このデータを GatsbyJS のプラグインを通して、GraphQL から取得します。

Airtableの画面

3. コードの説明

GraphQL 経由で取得されるデータは、タイトル等も含めた基本情報がオブジェクト配列形式で取得できます。tag 情報については、このオブジェクトの中の配列として取得できます。

console画面

3.1. JSX のコード

このオブジェクトの配列データを map 関数を使用して表示します。

./portfolio.js
{
  filteredData.map((edge) => {
    return (
      <div key={edge.node.data.title}>
        <li className={styles.list}>
          <div className={styles.imageWrapper}>
            <img
              src={edge.node.data.img ? edge.node.data.img[0].url : "#"}
              alt={edge.node.data.title}
              className={styles.image}
            />
          </div>

          <div className={styles.listContentsWrapper}>
            <p className={styles.listTitle}>{edge.node.data.title}</p>
            <p className={styles.description}>{edge.node.data.description}</p>
            {/* 中略 */}
          </div>
        </li>
      </div>
    );
  });
}

3.2. Set 関数による tag の配列データを用意

次に、画面上部に表示する絞り込み側のボタンを作成します。
tag は、ドロップダウンとは異なり、随時 tag 要素のデータが追加されるので、マスタデータのようなものがありません。したがって、tag のリストを、現在リスト情報で使用されているものから動的に作成し、配列 allTags に値を格納します。一旦 Set 関数をつかうことで、重複しない全 tag 情報を格納し、それを配列に変換します。

filterButtons

./portfolio.js
let allTags = new Set();
const uniqueTags = () => {
  airtableData.forEach((data) => {
    data.node.data.techStack.forEach((tag) => {
      allTags.add(tag);
    });
  });
  allTags = Array.from(allTags);
};
uniqueTags();

3.3. フィルタ関数の作成と className の動的付与

タグボタンをクリックすると、クリックしたタグと同じ項目を含む項目に絞り込む為の、フィルタ関数作成します。useState を使用します

クリックした tag をハイライト表示するように、className を動的に変更する為のコードを記述します。クリックした tag と同じ名前のリスト内の tag、両方ともに背景色を変更します(active class を付与)。

タグによるフィルタリング

./portfolio.js
const [filteredData, setFilteredData] = useState(airtableData);
const [filterActive, setFilterActive] = useState("");

const selectFilter = (e) => {
  const filteredAirtableData = airtableData.filter((data) => {
    return data.node.data.techStack.includes(e.target.textContent);
  });
  setFilterActive(e.target.textContent);
  setFilteredData(filteredAirtableData);
};

{
  /* 中略 */
}
{
  /* フィルタ用のボタンのコード */
}
<span
  key={tag}
  className={filterActive === tag ? "buttonTag active" : "buttonTag"}
  onClick={selectFilter}
>
  {tag}
</span>;

{
  /* 中略 */
}
{
  /* フィルタ用のボタンのコード */
}
<span
  key={item}
  onClick={selectFilter}
  className={filterActive === item ? "buttonTag active" : "buttonTag"}
>
  {item}
</span>;

3.5. Reset 機能

最後に Reset 機能を作成します

./portfolio.js
const resetFilter = () => {
  setFilterActive("");
  setFilteredData(airtableData);
};

4. まとめ

特別難しい機能ではないですが、よく使うと思うので、今後の参照用としてまとめてみました。

Discussion