本文までスキップする

【初心者向け】ReactでモダンなUIを実装しよう【Part1】

アバター画像
Takuma Yanagawa
/ 16 views

こんにちは。UIデザイナーの梁川です。

自身の知識の整理とアウトプットを兼ねて、Reactの入門記事をシリーズとして執筆することにしました。
「HTML/CSSとJavaScriptの基礎は書けるけれど、Reactはこれから」という方に参考にしていただけると幸いです。

Reactを学ぶアプローチはいろいろありますが、せっかくならモチベーションが上がるような「見た目のいいUI」を作りながら楽しく進めたいですよね。
このシリーズでは「Habit Tracker」を題材に、数回に分けて1つのアプリを完成させていきます。

Habit Trackerは、「毎日ストレッチをする」「本を10分読む」といった続けたい習慣を登録して、できた日にチェックを入れていく、シンプルな習慣管理アプリです。1週間分の日付が横に並び、習慣ごとにチェックを付けていくだけのアプリですが、Reactの基本はひととおり登場します。


まずは第1回、ヘッダー部分のUIを作っていくところから始めましょう。

今回作るもの

今回はHabit Trackerのヘッダー部分を構築します。

プロジェクトを作る

ビルドツールには Vite を使います。

ビルドツールとは、開発中に書いたコードをブラウザが読める形に変換したり、ファイルの変更を検知して画面を自動で更新したりしてくれる、開発の土台になるツールです。Viteはその中でも動作が速く、Reactの雛形もコマンド1つで用意してくれます。まずはそのコマンドでプロジェクトの雛形を作ります。

パッケージ管理には pnpm を使います(npm/yarnでも構いません)。パッケージ管理ツールは、Reactのような外部のライブラリをインストールしたり、そのバージョンを管理したりしてくれるものです。npm・yarnと役割は同じですが、pnpmはインストールが速く、ディスク容量を節約できるのが特徴です。

未インストールなら、先に入れておきます。

brew install pnpm   # npm install -g pnpm でも可

ViteのコマンドでReactプロジェクトの雛形を作ります。

mkdir react-basic && cd react-basic
pnpm create vite@latest .

対話式でいくつか聞かれるので、以下を選びます。

質問選択
Select a frameworkReact
Select a variantJavaScript + React Compiler
Which linter to use?ESLint

ここではJavaScriptを選びます。実務ではTypeScriptが主流ですが、Reactの書き方と型の書き方を同時に追いかけると、覚えることが一気に増えてしまいます。まずはReactに集中できるよう、このシリーズではJavaScriptで進めます。

作成できたら依存パッケージを入れて、開発サーバーを起動します。

# pnpm
pnpm install
pnpm dev
# npm
npm install
npm run dev
# yarn
yarn
yarn dev

ブラウザで表示されたURLを開いて、ViteのデフォルトのReact画面が出ればOKです。

使わないものを消す

Viteのテンプレートには、最初からロゴ画像やサンプルのCSSが入っています。今回はTailwindでスタイリングするので、不要なものを先に消しておきます。

  • src/assets/ をフォルダごと削除
  • src/App.css を削除
  • src/index.css を削除(あとでTailwind用に作り直します)
  • App.jsxmain.jsx から、消したCSSへの import 文も削除
// main.jsx
import './index.css'   // ← 一旦消す
// App.jsx
import './App.css'   // ← 一旦消す

Tailwindを導入する

スタイリングには Tailwind CSS を使います。flexpx-4bg-zinc-900 のような小さなクラスをHTMLに直接付けて見た目を組む、ユーティリティファーストのCSSフレームワークです。CSSファイルを別で書かずに、マークアップを見ながらスタイルを当てられるのが特徴です。

pnpm add tailwindcss @tailwindcss/vite

Viteの設定ファイルにプラグインを追加します。

// vite.config.js
import { defineConfig } from 'vite'
import react from '@vitejs/plugin-react'
import tailwindcss from '@tailwindcss/vite'

export default defineConfig({
  plugins: [react(), tailwindcss()],
})

src/index.css を新しく作り、Tailwindを読み込む1行だけ書きます。

/* src/index.css */
@import "tailwindcss";

main.jsx に再度 import を追加します。

// main.jsx
import './index.css'

これでTailwindのクラスが使えるようになりました。

ヘッダーを作る

ここからいよいよ実装に入ります。

Reactでは、画面をひとかたまりのHTMLとして書くのではなく、意味のある単位に分けた関数として組み立てます。Figmaのコンポーネントとイメージは同じです。

今回作成するヘッダーは、アプリ全体から見ると独立した1つの塊です。なので Header という専用の関数に切り出します。

// App.jsx
export default function App() {
  return (
    <div className="max-w-6xl mx-auto p-4 flex flex-col gap-4">
      <Header />
    </div>
  );
}

function Header() {
  return (
    <div>
      <header className="flex items-center justify-between p-4">
        <div className="flex flex-col gap-1">
          <h1 className="text-3xl">Habit Tracker</h1>
          <p className="text-zinc-400 text-sm">Your personal habit tracking app</p>
        </div>
        <div className="flex flex-col items-end gap-4">
          <span className="text-zinc-400 text-sm pr-4">Apr/1 - Apr/7</span>
          <div className="flex items-center gap-2">
            <button className="bg-zinc-800 hover:bg-zinc-200 text-white hover:text-black transition-colors duration-200 ease-out rounded-full px-6 py-3">
              Prev
            </button>
            <button className="bg-zinc-800 hover:bg-zinc-200 text-white hover:text-black transition-colors duration-200 ease-out rounded-full px-6 py-3">
              Next
            </button>
          </div>
        </div>
      </header>
    </div>
  );
}

JSXとは

return の中の <div>...</div> は、HTMLのように見えますが、これは JSX という記法です。JavaScriptの中にHTMLのようなタグを直接書けるようにしたReactの構文で、最終的にReactがブラウザで動くJavaScriptに変換してくれます。

見た目はHTMLとほぼ同じですが、いくつか違いがあります。

  • class ではなく className と書く(classはJavaScriptの予約語のため)
  • 属性はキャメルケース(onclickonClick
  • { } で囲むと、中にJavaScriptの値や式を埋め込める
  • 返すタグは1つの親要素にまとめる必要がある(コードで全体を <div> が包んでいるのはこのため)

上のコードで押さえるポイントは2つあります。

1. Header は普通のJS関数

function Header() { ... } と、return の中にJSXを書きます。特別な構文があるわけではなく、「UIを返す関数」というだけのものです。

2. <Header /> で呼び出す

App の中では <Header /> と、自作のHTMLタグのように呼び出しています。これがコンポーネントの使い方で、「関数を、タグとして画面に置ける」のがReactの基本の仕組みです。

いきなり1つの巨大な関数に全部書くこともできますが、意味のある単位(ヘッダー、リスト、フォームなど)で分けておくと、後から「ヘッダーだけ直したい」といった変更がしやすくなります。

Tailwindでレイアウトを組む

Tailwindのクラスは基本的にCSSのプロパティと1対1で対応しています。
いくつか法則を知るだけで、一気に書きやすくなります。

余白やサイズは「4の倍数」

数字が付くクラス(gap-4px-6p-2 など)のサイズは、数字 × 0.25rem(=4px) で決まります。4→1rem(16px)、8→2rem(32px)、5→1.25rem(20px)、p-2なら8px…という具合に、全部この規則です。

色は「色名 + 50〜950の濃さ」

色のクラス(bg-zinc-800text-zinc-400 など)は、色名+濃さ(50〜950) の組み合わせです。数字が小さいほど明るく、大きいほど暗くなります(zinc-50はほぼ白、zinc-900はほぼ黒)。zincはグレー系のパレットで、ほかにslateredblueなどがあり、どれも同じ50〜950のスケールで揃っています。

少しだけ、今回使った主要なクラスをいつものCSSに翻訳してみましょう。

左右に配置する

flex items-center justify-between
TailwindCSS
flexdisplay: flex;
items-centeralign-items: center;
justify-betweenjustify-content: space-between;

縦に積んで右揃えにする

flex flex-col items-end gap-4
TailwindCSS
flex-colflex-direction: column;
items-endalign-items: flex-end;
gap-4gap: 1rem;

ボタンのスタイリング

bg-zinc-800 hover:bg-zinc-200 text-white hover:text-black
transition-colors duration-200 ease-out
rounded-full px-6 py-3
TailwindCSS
bg-zinc-800background-color: #27272a;
hover:bg-zinc-200:hover { background-color: #e4e4e7; }
text-white / hover:text-blackcolor: #fff;:hover { color: #000; }
transition-colorstransition-property: color, background-color, ...;
duration-200transition-duration: 200ms;
ease-outtransition-timing-function: ease-out;
rounded-fullborder-radius: 9999px;
px-6padding-inline: 1.5rem;
py-3padding-block: 0.75rem;

hover: を頭につけるだけで疑似クラスが使えます。アニメーションも transition-colors などを組み合わせるだけで、CSSファイルを行ったり来たりせずにサクッと実装できるのがTailwindの魅力ですね。

まとめ

第1回は以上です。おつかれさまでした。
最後に今回触れたReactの基本をざっくりおさらいしておきましょう。

  • コンポーネント:UIを返すJavaScriptの関数。<Header /> のようにタグとして呼び出して使います。
  • JSX:JavaScriptの中にHTMLのようなタグを書ける記法。class が className になるなどの小さな違いはありますが、ほぼHTML感覚です。
  • Tailwind CSS:HTML(JSX)に直接クラスを書き込んでいくCSSフレームワーク。

今回はまだヘッダーができただけですが、自分の書いたコードがきれいなUIとして画面に表示されるとやっぱりモチベーションが上がりますよね。次回以降もこのように実際のUIを組み立てながら、Reactの機能を少しずつ紐解いていきます。

参考