stock.dev
Next.jsの勉強会 vol.6 ファイル分割(components・data・types)

Next.jsの勉強会 vol.6 ファイル分割(components・data・types)

·6 min read

今回学ぶこと

Next.jsでページを作っていると、1つのpage.tsxにコードが増えていく。 最初は1ファイルで書く方が分かりやすいが、コンポーネント、データ、型が混ざると読みにくくなる。そこで、役割ごとにファイルを分ける。

src/components
UI部品を置く
 
src/data
表示用データを置く
 
src/types
型定義を置く

コンポーネントを別ファイルに移す

もともとServiceCardsrc/app/page.tsxの中に書いていた。

function ServiceCard({ title, description, price }: ServiceCardProps) {
  return (
    <article className="border border-zinc-200 bg-white p-6 shadow-sm">
      <h3 className="text-xl font-semibold">{title}</h3>
      <p className="mt-4 leading-7 text-zinc-600">{description}</p>
      <p className="mt-6 border-t border-zinc-200 pt-4 text-sm font-semibold text-zinc-950">
        {price}
      </p>
    </article>
  );
}

これを次のファイルに移した。

src/components/service-card.tsx

exportで外から使えるようにする

別ファイルに移したコンポーネントは、他のファイルから読み込めるようにexportする。

export function ServiceCard({ title, description, price }: ServiceCardProps) {
  return (
    <article className="border border-zinc-200 bg-white p-6 shadow-sm">
      <h3 className="text-xl font-semibold">{title}</h3>
      <p className="mt-4 leading-7 text-zinc-600">{description}</p>
      <p className="mt-6 border-t border-zinc-200 pt-4 text-sm font-semibold text-zinc-950">
        {price}
      </p>
    </article>
  );
}

exportを付けることで、別ファイルからServiceCardをimportできる。

importで読み込む

src/app/page.tsxでは、切り出したServiceCardを読み込む。

import { ServiceCard } from "@/components/service-card";

この@/components/service-cardは、src/components/service-card.tsxを指している。

このプロジェクトでは@/src/を表す設定になっているためである。

@/components/service-card

src/components/service-card.tsx

なぜ分けるのか

ファイルを分けると、page.tsxの役割が分かりやすくなる。

page.tsxは、ページ全体の構成を担当する。

ServiceCardは、サービスカード1枚の見た目を担当する。

page.tsx
ページ全体の構成
 
service-card.tsx
カードUIの部品

このように役割を分けることで、あとから修正する場所を見つけやすくなる。

データを別ファイルに移す

ServiceCardを切り出したあと、サービス一覧のデータもpage.tsxから分離した。

src/data/services.ts

このファイルには、サービス一覧として表示するデータを置く。

type Service = {
  title: string;
  description: string;
  price: string;
};
 
export const services: Service[] = [
  {
    title: "コーポレートサイト制作",
    description:
      "会社の強みや問い合わせ導線を整理して、信頼感のあるWebサイトに仕上げます。",
    price: "80万円から",
  },
];

export const servicesと書くことで、他のファイルからサービスデータを読み込める。

page.tsxでデータを読み込む

page.tsxでは、servicesをimportして使う。

import { services } from "@/data/services";

これにより、page.tsxからデータ定義が消え、ページ本体が読みやすくなった。

page.tsx
ページ全体の構成
 
service-card.tsx
カードUI
 
services.ts
サービスの表示データ

コンポーネントとデータを分けることで、UIを直したいときはcomponents、表示内容を直したいときはdataを見る、という判断がしやすくなる。

型を別ファイルに移す

Lesson40では、Service型をsrc/types/service.tsに移した。

src/types/service.ts

型定義は次のように書く。

export type Service = {
  title: string;
  description: string;
  price: string;
};

export typeを使うことで、他のファイルからService型を読み込める。

dataファイルで型を読み込む

src/data/services.tsでは、Service型をimport typeで読み込む。

import type { Service } from "@/types/service";

import typeは、型だけを読み込むための書き方である。

実行時に使う値ではなく、TypeScriptの型チェックにだけ使う。

その上で、services配列に型を付ける。

export const services: Service[] = [
  {
    title: "コーポレートサイト制作",
    description:
      "会社の強みや問い合わせ導線を整理して、信頼感のあるWebサイトに仕上げます。",
    price: "80万円から",
  },
];

これにより、services配列の各データはService型に合っている必要がある。

例えばpriceを書き忘れると、TypeScriptがエラーとして教えてくれる。

components・data・typesの役割

ここまでで、ファイルの役割は次のように分かれた。

src/components/service-card.tsx
カードUI
 
src/data/services.ts
サービスの表示データ
 
src/types/service.ts
サービスデータの型

役割を分けることで、コードの見通しがよくなる。

UIを直すならcomponents、表示内容を直すならdata、データの形を直すならtypesを見る、という判断ができる。