React入門第3回 ~コンポーネントのスタイル・分割・Fragment〜

はじめに

プロ太
プロ太

OZくん、前回までにコンポーネントの基本的な作り方は理解できましたか?

はい!コンポーネントは再利用可能なUIのパーツで、JSXを使って書くんですよね。でも先生、コンポーネントのデザインってどうやって付けるんですか?

いい質問ですね!今日はコンポーネントにスタイルを適用する方法と、コンポーネントを分割する方法について学んでいきましょう。

1.CSSでコンポーネントをスタイリングする

まずは簡単なコンポーネントを作って、スタイルを適用してみましょう。

import "./Example.css";

const Example = () => {
  return (
    <div className="component">
      <h3>こんにちは!OZくん!</h3>
    </div>
  );
};

export default Example;
.component {
  padding: 2rem;
  color: red;
  border: 5px solid green;
}

あれ?HTMLではclass=”component”って書いていたと思うんですけど、classNameになってるんですね?

よく気付きましたね!ReactではHTMLのclass属性の代わりにclassNameを使います。これはJavaScriptで’class’が予約語として使われているためです。ちなみに、最新のReactでは、classと書いても問題なく動作するんですが、可読性を上げるために、classNameを使いましょう

なるほど!でも、CSSファイルはどうやってコンポーネントと結びつけているんですか?

import "./Example.css";

それはimport "./Example.css"の部分で行っています。このように直接CSSファイルをインポートすることで、そのコンポーネントにスタイルを適用できるんです。

2.コンポーネントを分割する

次は、コンポーネントを複数のファイルに分割する方法を見ていきましょう。まずは、なぜコンポーネントを分割するのか理解することが大切です。

どうして分割する必要があるんですか?

主に3つの理由があります。

  1. コードの管理がしやすくなる
  2. コンポーネントの再利用が簡単になる
  3. チームでの開発がスムーズになる

実際のコードを見ながら詳しく説明していきましょう。

// App.jsx
import Greeting from "./components/Greeting";
import Profile from "./components/Profile";

const App = () => {
  return (
    <div>
      <Greeting />
      <Profile />
    </div>
  );
};

export default App;
const Greeting = () => {
  return (
    <div>
      <h1>こんにちは!</h1>
      <p>ようこそReactへ!</p>
    </div>
  );
};

export default Greeting;
const Profile = () => {
  return (
    <div>
      <h2>プロフィール</h2>
      <ul>
        <li>名前:OZくん</li>
        <li>趣味:プログラミング</li>
      </ul>
    </div>
  );
};

export default Profile;

ファイルが3つに分かれていて、Greeting.jsxとProfile.jsxのファイルはcomponentsフォルダに入っています。それぞれのファイルの役割を説明します。

  1. App.jsx
    • アプリケーションのメインとなるコンポーネント
    • 他のコンポーネントをimportして組み合わせています
    • import Greeting from "./components/Greeting"の部分で他のコンポーネントを読み込んでいます
  2. Greeting.jsx
    • 挨拶文を表示する部分を担当するコンポーネント
    • export default Greetingで他のファイルから使えるようにしています
  3. Profile.jsx
    • プロフィール情報を表示する部分を担当するコンポーネント
    • これもexport default Profileで他のファイルから使えるようにしています

componentsフォルダを作っているのは何か理由があるんですか?

componentsフォルダを作る理由は、

  • コンポーネントファイルを整理して管理しやすくする
  • プロジェクトの構造を分かりやすくする
  • チームの他のメンバーが必要なコンポーネントを見つけやすくなる

プロジェクトが大きくなるほど、このような整理整頓が重要になってきます。

なるほど!じゃあ、importとexportの書き方についてもう少し詳しく教えてください!

コンポーネントのインポート・エクスポートには2つの重要なポイントがあります。以下のコードを見てください。

1.エクスポート(export)の方法

// 方法1:デフォルトエクスポート
export default Greeting;

// 方法2:名前付きエクスポート
export const Greeting = () => { ... };

2.インポート(import)の方法

// デフォルトエクスポートされたものをインポートする場合
import Greeting from "./components/Greeting";

// 名前付きエクスポートされたものをインポートする場合
import { Greeting } from "./components/Greeting";

基本的には、1つのファイルには1つのコンポーネントを置き、export defaultを使うのがシンプルで分かりやすいですよ。

なるほど!分かりました!!今日はありがとうございました!!

補足:exportとexport defaultの違い

// Example.jsx
import Child from "./components/Child";

const Example = () => {
  return <Child />;
};

export default Example;
// Child.jsx
import "./Child.css";
import { List } from "./List.jsx";

const Child = () => {
  return (
    <div className="component">
      <h3>コンポーネントを作ってみよう!</h3>
      <List />
    </div>
  );
};

export default Child;
// List.jsx
const List = () => {
  return (
    <ul>
      <li>項目-1</li>
      <li>項目-2</li>
      <li>項目-3</li>
      <li>項目-4</li>
      <li>項目-5</li>
    </ul>
  );
};

export { List };
/* Child.css */
.component {
  padding: 1rem;
  color: blue;
  border: 5px solid blue;
}
  • export defaultは、そのファイルのメインとなるコンポーネントを指定する時に使います。1ファイルに1つだけ使えます
  • 普通のexportは、複数のものをエクスポートでき、変数なども一緒にexportすることができます。インポートする時はimport { List } from './List'のように波括弧{}を使う必要があります。

Fragmentについて

数日後、、、

プロ太先生!今日はReactの勉強中に困ったことがあるんです!
こんなコードを書いたんですけど、エラーになっちゃって…

const Child = () => {
  return (
    <div className="component">
      <h3>こんにちは!OZくん</h3>
    </div>
    <h3>Fragmentを使ってみよう!</h3>
    <p>エラーが出ずに出力できるかな?</p>
  );
};

なるほど!これは多くの初学者がつまづくポイントですね。Reactのコンポーネントでは、returnする要素は必ず1つの親要素でまとめないといけないんです。なので、以下のようなコードに変更しましょう。

const Child = () => {
  return (
    <div>
      <div className="component">
        <h3>こんにちは!OZくん</h3>
      </div>
      <h3>Fragmentを使ってみよう!</h3>
      <p>エラーが出ずに出力できるかな?</p>
    </div>
  );
};

divで囲って、1つの親要素でまとめる方法でエラーは解決できます!でも、これだと、必要のないdiv要素が増えてしまいますよね。HTMLの構造が複雑になってしまうんです。

確かに…。でも他に方法はあるんですか?

そこで登場するのが「Fragment」です!まずは基本的な書き方を見てみましょう。

import React from "react";

const Child = () => {
  return (
    <React.Fragment>
      <div className="component">
        <h3>こんにちは!OZくん</h3>
      </div>
      <h3>Fragmentを使ってみよう!</h3>
      <p>エラーが出ずに出力できるかな?</p>
    </React.Fragment>
  );
};

おお!余計なdivがなくなりました!でもReact.Fragmentって少し長くないですか?

その通り!もっと短く書く方法もあります。Fragmentを直接インポートする方法です。

import { Fragment } from "react";

const Child = () => {
  return (
    <Fragment>
      {/* 中身は同じ */}
    </Fragment>
  );
};

そして、さらに簡単な書き方があります!空のタグ<></>を使う方法です!

const Child = () => {
  return (
    <>
      <div className="component">
        <h3>こんにちは!OZくん</h3>
      </div>
      <h3>Fragmentを使ってみよう!</h3>
      <p>エラーが出ずに出力できるかな?</p>
    </>
  );
};

わぁ!すっきりしました!これが一番簡単ですね!

そうですね。この空タグの書き方が最も一般的です。ちなみに、FragmentにはclassNameのようなスタイルに関する属性はつけることができないので、CSSを全体にあてたりはできません。

なるほど!!確かに全体を囲っているから、backgroundcolorとかつけてしまいそうです。でも、できないんですね。わかりました!!

ただ、実はkey属性だけは特別で、<Fragment>につけることができます。これはループ処理で要素を繰り返し表示する時によく使うんですが…これについては今後の「リストレンダリング」の回で詳しく説明しますね!今は、key属性だけ、<Fragment>につけることができるということを理解しておいてください。

なるほど!!とりあえず今日は、空タグ<></>を使えばいいんですね!

まとめ

では、今日学んだことを整理しておきましょう!

  1. コンポーネントのスタイリング
    • CSSファイルをimportして使用する
    • class属性の代わりにclassNameを使う
  2. コンポーネントの分割
    • 複数のファイルに分けることで管理しやすくなる
    • export defaultとexportを使い分ける
    • コンポーネント間で組み合わせて使える
  3. フラグメントについて
    • Reactのコンポーネントは必ず1つの親要素でまとめる必要がある
    • 不要なdivを避けるためにフラグメントを使用する
    • フラグメントは3つの書き方がある(<React.Fragment><Fragment><></>
    • 通常は空タグ<></>を使うのがシンプルで推奨される書き方
    • フラグメントにはclassNameなどのスタイリング属性は使えない

わかりやすかったです!!次回も楽しみです!!