2
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

【React × TypeScript】propsで渡すデータに列挙型(enums)をつける方法

Last updated at Posted at 2021-04-02

要約

こう書いてもいいですが

const Tags = [ "React", "Redux Toolkit", "Firebase", "Tailwind CSS" ]

TypeScriptで列挙型(enums)をつけてみましょうという話です。

enum TagTypes = {
  react = "React",
  toolkit = "Redux Toolkit",
  firebase = "Firebase",
  tailwind = "Tailwind CSS",
}
export default TagTypes;
import TagTypes;

const Tags = [
  TagTypes.react,
  TagTypes.toolkit,
  TagTypes.firebase,
  TagTypes.tailwind,
]

## やったこと ![スクリーンショット 2021-04-02 19.51.10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1028795/f477863e-d6f8-8422-867c-759121c15dbe.png) よくある成果物一覧ページをNext.jsで作りました。 画像やリンク、タグ名などのpropsをPortfolioItemコンポーネントにまず渡して、その中でTagコンポーネントにタグ名を渡しています。 その際、ある方のGithubコードを参考に、タグに列挙型をつけることができたので共有します。 ## 方法 ①まずTagTypes.tsファイルを`root/src/enums/`に作ります。 タグは他のPortfolioItemコンポーネントでも利用されるのでズラーっと定義しておきます。
enum TagTypes = {
  html = "HTML",
  css = "CSS",
  jquery = "jQuery",
  javascript = "JavaScript",
  react = "React",
  toolkit = "Redux Toolkit",
  next = "Next.js",
  rails = "Rails",
  firebase = "Firebase",
  rspec = "RSpec",
  heroku = "Heroku",
  bootstrap = "Bootstrap",
  tailwind = "Tailwind CSS",
  vercel = "Vercel",
}

export default TagTypes; //忘れずに

②次にこのTagTypes.tsをインポートして、キーを指定する形でタグを設定します。
↓Portfolio.tsx

import type { VFC } from "react";
import Head from "next/head";
import Layout from "src/components/Layout";
import PortfolioItem from "src/components/PortfolioItem";
import TagTypes from "src/enums/TagTypes";  // TagTypesをインポート。

const PORTFOLIO_ITEMS = [
  {
    href: "https://moyong-front.web.app/",
    src: "/workoutJournal.png",
    name: "Workout Journal",
    created_at: "2021/3",
    tags: [
      TagTypes.react,  // "React"のような文字列の代わりに、先ほど定義したTagTypesのキーを指定する。 
      TagTypes.toolkit,
      TagTypes.firebase,
      TagTypes.tailwind
    ],  
    text: [
      "日々の筋トレを記録できるアプリです。",
      "主な機能としては、ログイン機能、投稿機能、コメント機能、GitHubカレンダー機能です。",
      "構成は React / Redux Toolkit / Typescript / Firebase です。",
      "UIはTailwind CSSとMaterial UIを使用しています。",
    ],
  },
];
const Works: VFC = () => {
  return (
    <>
      <Head>
        <title>Portfolio | MO4g-DEV</title>
      </Head>
      <Layout>
        <div className="flex flex-col justify-center items-center">
          {PORTFOLIO_ITEMS.map((item) => (
            <PortfolioItem
              href={item.href}
              src={item.src}
              name={item.name}
              created_at={item.created_at}
              tags={item.tags} // ここで渡す。
              text={item.text}
            />
          ))}
        </div>
      </Layout>
    </>
  );
};
export default Works;

③ここでもTagTypes.tsをインポートして、PROPS型を定義して、子のTechTagコンポーネントにタグ名を渡します。
↓PortfolioItem.tsx

import React, { VFC } from "react";
import Image from "next/image";
import TechTag from "src/components/TechTag";
import ScheduleIcon from "@material-ui/icons/Schedule";
import TagTypes from "src/enums/TagTypes"; // TagTypesをインポート。
interface PROPS {
  href: string,
  src: string,
  name: string,
  created_at: string,
  tags: TagTypes[], // enumsをつけないならstring[]となりますが、TagTypes[]とした方がより厳密。
  text: string[],
}
const PortfolioItem: VFC<PROPS> = (props) => {
  const { href, src, name, created_at, tags, text } = props;
  return (
    <div className="flex flex-col w-11/12 my-5 xl:py-5 xl:px-10 border shadow-md xl:flex-row">
      <a
        className="flex justify-center items-center mt-5 xl:mt-0 xl:w-2/5"
        href={href}
        target="_blank"
        rel="noopener noreferrer"
      >
        <Image src={src} width={450} height={270} />
      </a>
      <div className="flex flex-col justify-center items-center m-5 xl:w-3/5 xl:justify-start xl:items-start">
        <h1 className="text-lg text-black xl:text-2xl font-bold">{name}</h1>
        <p className="text-sm text-black xl:mt-2">
          <ScheduleIcon className="text-sm mx-1" />
          {created_at}
        </p>
        <div className="flex mt-2">
          {tags.map((tag) => (
            <TechTag name={tag} > // タグ名をnameという名前でTechTagコンポーネントに渡す。
          ))}
        </div>
        <div className="mt-2 sm:w-4/5 md:2/3 xl:w-full">
          {text.map((row) => (
            <p className="text-sm text-black xl:text-base xl:my-1">{row}</p>
          ))}
        </div>
      </div>
    </div>
  );
};
export default PortfolioItem;

④あとは渡されたタグ名を表示します。
↓TechTag.tsx

import { VFC } from "react";

interface  PROPS {
  name: string;
}

const TechTag: VFC<PROPS> = (props) => {
  const { name } = props;
  return <div className="text-xs p-1 mx-1 rounded-sm shadow-inner bg-tag text-white sm:text-sm font-medium">{name}</div>;
}

export default TechTag;

なぜやるのか

今回定義したTagTypes型は、例として以下のタグが同時に存在しないことを保証してくれます。
・Redux Toolkit
・Redux Tooklit (タイポ)
・Redux ToolKit (toolkitのkが大文字)
いずれも文字列なので、string型では統一しきれないわけです。

(・x・ ).o0○(分かりやすい文章書きたい...)
たとえ記事に関係ないことでも、疑問等コメントしていただけると嬉しいです!

2
1
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
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?