要約
こう書いてもいいですが
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,
]
## やったこと  よくある成果物一覧ページを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○(分かりやすい文章書きたい...)
たとえ記事に関係ないことでも、疑問等コメントしていただけると嬉しいです!