All Articles

タグを全部表示するコンポーネントを作成する

2019/08/27

対応前後の差分

右下のタグ群のコンポーネントを作成する

2019 08 29 13 39 52

作成するファイル

タグ一覧を表示するコンポーネント TagList を作成する

新規作成するファイル

TagList/

  • index.js
  • TagList.js
  • TagList.module.scss

※既存のプロジェクトの構成をそのまま踏襲

index.js

// @flow
export { default } from './TagList';

TagList.js

useStaticQueryで、全Tagを取得して、mapでliタグとして追加していく処理

// @flow
import React from 'react';
import kebabCase from 'lodash/kebabCase';
import { Link } from 'gatsby';
import { useTagsList } from '../../../hooks';
import styles from './TagList.module.scss';


const TagList = () => {
  const tags = useTagsList();
    return (
      <div className={styles['tag']}>
        <ul className={styles['tag__list']}>
          {tags.map((tag) => (            
            <li className={styles['tag__list-item']} key={tag.fieldValue}>
              <Link className={styles['tag__list-item-link']} to={`/tag/${kebabCase(tag.fieldValue)}/`} >
                {tag.fieldValue}
              </Link>
            </li>
          ))}
        </ul>
      </div>
    );
};

export default TagList;

TagList.module.scss

リスト表示を横並びにするためにflex指定し、リストタグ関連のデフォルトの装飾を無効にして他はよしなにデザイン装飾。
(scss自体を似たようなコンポーネントからコピペして修正して対応してます。)

@import '../../../assets/scss/variables';
@import '../../../assets/scss/mixins';

.tag {
    @include margin-bottom(1);

    &__list {
      display: flex;
      flex-flow: row wrap;
      flex-grow: 0;
      flex-shrink: 0;
      list-style: none;
      padding: 0;
      margin: 10px -3px;
      background:none;
      border-radius: none;
      box-shadow: none;    
      
      &-item {
        padding: 2px;
        margin: 4px;
        display: flex;
        align-content: center;
        align-items: center;
        justify-content: center;
        height: $button-height;
        line-height: $button-height;        
        background-color:  $color-gray-light;
        text-align: center;
        
        &-link {
          border: 0;
          display: flex;
          color: $color-base;
          font-size: 9px;
          align-content: center;
          align-items: center;
    
          &:hover,
          &:focus {
            color: $color-gray;
          }
        }

      }

    }

}

Sidebarコンポーネントに追加

Sidebar内のContactsコンポーネントの下に配置して完了。

const Sidebar = ({ isIndex }: Props) => {
  const { author, copyright, menu } = useSiteMetadata();

  return (
    <div className={styles['sidebar']}>
      <div className={styles['sidebar__inner']}>
        <Author author={author} isIndex={isIndex} />
        <Menu menu={menu} />
        <Contacts contacts={author.contacts} />        
        <TagList />
        <Copyright copyright={copyright} />
      </div>
    </div>
  );
};

タグを全て取得する処理(useStaticQuery)

ページ以外のコンポーネントなので、普通のgraphqlのクエリが使えない。
そのため、以下のような、ページ以外でもgraphqlクエリが使える useStaticQuery を使う。

import React from "react"
import { useStaticQuery, graphql } from "gatsby"

const NonPageComponent = () => {
  const data = useStaticQuery(graphql`
    query NonPageQuery {
      site {
          title
      }
    }
  `)

  return (
    <h1>
      {data.site.title}
    </h1>
  )
}

全タグ取得処理(useStaticQuery利用)が、定義済みだったのでそれを使った

src > hooks 配下に、 use-tag-list.js が作成されていて、全タグ取得のクエリが定義済みだったので、これをそのまま使いました。

// @flow
import { useStaticQuery, graphql } from 'gatsby';

const useTagsList = () => {
  const { allMarkdownRemark } = useStaticQuery(
    graphql`
      query TagsListQuery {
        allMarkdownRemark(
          filter: { frontmatter: { template: { eq: "post" }, draft: { ne: true } } }
        ) {
          group(field: frontmatter___tags) {
            fieldValue
            totalCount
          }
        }
      }
    `
  );

  return allMarkdownRemark.group;
};

export default useTagsList;

useStaticQueryファイルの置き場所

src > hooks 配下には、取得したいデータごとのクエリが書いてあるファイルが配置されている状態。
それぞれ、サイトの基本情報、全カテゴリ、全タグを取得する処理が定義されていた。

src > hooks 
           > use-site-metadata.js
           > use-categories-list.js
           > use-tags-list.js

use-site-metadata.jsの中身

// @flow
import { useStaticQuery, graphql } from 'gatsby';

const useSiteMetadata = () => {
  const { site } = useStaticQuery(
    graphql`
      query SiteMetaData {
        site {
          siteMetadata {
            author {
              name
              bio
              photo
              contacts {
              #  email
              #  telegram
                twitter
              #  github
              #  rss
              #  vkontakte
              }
            }
            menu {
              label
              path
            }
            url
            title
            subtitle
            copyright
            disqusShortname
          }
        }
      }
    `
  );

  return site.siteMetadata;
};

export default useSiteMetadata;

useStaticQueryファイルの使い方

上記のファイルを使って、データ取得する流れは以下

1: 定義済みクエリをimportする
2: クエリ結果を変数に格納し、ドット「.」でアクセスして使う

例) useSiteMetadata

// 1: hooksのパスを指定して、const定義した値(useSiteMetadata)をimportする
import { useSiteMetadata } from '../../../hooks';

const Author = () => {
  // author変数に取得したデータを格納する
  const { author } = useSiteMetadata();

  return (
    <div className={styles['author']}>
          
          // 2: author変数に、ドット[.]で該当データにアクセスして取り出す
          <strong>{author.name}</strong>
        </a>
      </p>
    </div>
  );
};

export default Author;

終わりに

スターターで立ち上げたプロジェクトなので、すでに有識者のコードが定義されているので、その処理を見るだけでも学びがある。
記事一覧画面をテキストだけじゃなく、画像+説明文というようなOGPのようなコンポーネント並べるような修正をしたいし、あれもしたいし、これもしたい。()