デザインについての学習メモブログ

React入門 #01 – 基礎からコンポーネント作成まで完全ガイド(JavaScript & TypeScript対応)

記事内に広告が含まれています。

React入門 #01 – 基礎からコンポーネント作成まで完全ガイド(JavaScript & TypeScript対応)

この記事では、React初心者の方がゼロから基礎を学べるよう、Reactの概要から実際のコンポーネント作成まで、段階的に解説していきます。

最近の開発現場ではTypeScriptが主流になっているため、JavaScriptとTypeScriptの両方のコード例を掲載しています。

1. Reactとは?

Reactは、Meta(旧Facebook)が開発したJavaScriptライブラリで、ユーザーインターフェース(UI)を構築するために使われています。

Reactの特徴

コンポーネントベース
UIを再利用可能な部品(コンポーネント)に分割して開発できます。ヘッダー、ボタン、カードなど、それぞれを独立したコンポーネントとして作成し、組み合わせてアプリを構築します。

宣言的なUI
「どのように表示するか」ではなく「何を表示するか」を記述します。状態が変わると、Reactが自動的にUIを更新してくれます。

仮想DOM
Reactは仮想DOMという仕組みを使い、効率的に画面を更新します。変更が必要な部分だけを検出して更新するため、高速に動作します。

なぜReactを学ぶのか?

  • 世界中で広く使われており、求人需要が高い
  • 大規模なアプリケーション開発に適している
  • 豊富なライブラリやツールのエコシステム
  • React Nativeでモバイルアプリも開発できる

TypeScriptとは?

TypeScriptはJavaScriptに型システムを追加した言語で、Microsoftが開発しています。

コードを書く段階でエラーを検出でき、大規模開発に適しています。

TypeScriptのメリット:

  • エディタの補完機能が強力になる
  • バグを早期に発見できる
  • コードの可読性・保守性が向上する
  • 大規模プロジェクトで特に効果を発揮する

2. 開発環境を整えよう

必要なツール

Node.jsとnpm Node.jsをインストールすると、npmというパッケージ管理ツールも一緒にインストールされます。

  • Node.js公式サイトからダウンロード
  • LTS(長期サポート)版を選択するのがおすすめ

インストール後、ターミナルで確認:

Bash
node -v
npm -v

Node.jsについては、以下の記事で入門編を解説しています。

プロジェクトの作成

JavaScriptプロジェクト

Bash
npm create vite@latest my-react-app -- --template react
cd my-react-app
npm install
npm run dev

TypeScriptプロジェクト

Bash
npm create vite@latest my-react-app-ts -- --template react-ts
cd my-react-app-ts
npm install
npm run dev

これ(npm run dev)でローカルサーバーが起動し、ブラウザでhttp://localhost:5173にアクセスできます。

プロジェクト構成の理解

JavaScript版

TypeScript版

💡ポイント

TypeScript版では.jsx.tsxになり、tsconfig.jsonという設定ファイルが追加されます。

3. 初めてのReactアプリ

main.jsxの役割

JavaScript版(main.jsx):

JSX
import React from 'react'
import ReactDOM from 'react-dom/client'
import App from './App.jsx'
import './index.css'

ReactDOM.createRoot(document.getElementById('root')).render(
  <React.StrictMode>
    <App />
  </React.StrictMode>,
)

TypeScript版(main.tsx):

TSX
import React from 'react'
import ReactDOM from 'react-dom/client'
import App from './App.tsx'
import './index.css'

ReactDOM.createRoot(document.getElementById('root')!).render(
  <React.StrictMode>
    <App />
  </React.StrictMode>,
)

違いのポイント:

TypeScript版ではgetElementById('root')!と最後に!がついています。

これは「この要素は確実に存在する」とTypeScriptに伝えるための記法です。

App.jsxを編集してみよう

JavaScript版(App.jsx):

JSX
function App() {
  return (
    <div>
      <h1>Hello React!</h1>
      <p>初めてのReactアプリです</p>
    </div>
  )
}

export default App

TypeScript版(App.tsx):

TSX
function App() {
  return (
    <div>
      <h1>Hello React!</h1>
      <p>初めてのReactアプリです</p>
    </div>
  )
}

export default App

違いのポイント:

シンプルなコンポーネントの場合、JavaScriptとTypeScriptでほとんど違いはありません。

4. JSXの書き方と基本ルール

JSX(JavaScript XML)は、JavaScriptの中にHTML風の構文を書ける拡張構文です。

TypeScriptではTSXと呼ばれますが、書き方は同じです。

JSXの基本

JavaScript版:

JSX
// JSX
const element = <h1>こんにちは</h1>

// JavaScriptの式を埋め込む
const name = "太郎"
const greeting = <h1>こんにちは、{name}さん</h1>

TypeScript版:

TSX
// TSX
const element: JSX.Element = <h1>こんにちは</h1>

// TypeScriptの式を埋め込む
const name: string = "太郎"
const greeting: JSX.Element = <h1>こんにちは、{name}さん</h1>

違いのポイント:

TypeScript版では変数に型注釈(: string: JSX.Element)を付けることができます。ただし、型推論があるので省略しても問題ありません。

JSXの重要なルール

1. 必ず一つの親要素で囲む

JSX
// ❌ NG:複数の要素を並べられない
function App() {
  return (
    <h1>タイトル</h1>
    <p>本文</p>
  )
}

// ✅ OK:divで囲む
function App() {
  return (
    <div>
      <h1>タイトル</h1>
      <p>本文</p>
    </div>
  )
}

// ✅ OK:フラグメントを使う(余計なdivを作らない)
function App() {
  return (
    <>
      <h1>タイトル</h1>
      <p>本文</p>
    </>
  )
}

この規則はJavaScript版もTypeScript版も同じです。

2. JavaScriptの式は{}で囲む

JavaScript版:

JSX
function App() {
  const count = 5
  const isActive = true

  return (
    <div>
      <p>カウント: {count}</p>
      <p>2倍: {count * 2}</p>
      <p>状態: {isActive ? "アクティブ" : "非アクティブ"}</p>
    </div>
  )
}

TypeScript版:

TSX
function App() {
  const count: number = 5
  const isActive: boolean = true

  return (
    <div>
      <p>カウント: {count}</p>
      <p>2倍: {count * 2}</p>
      <p>状態: {isActive ? "アクティブ" : "非アクティブ"}</p>
    </div>
  )
}

3. classはclassNameを使う

JSX
// ❌ NG:classは予約語
<div class="container">...</div>

// ✅ OK:classNameを使う
<div className="container">...</div>

4. 自己閉じタグにはスラッシュが必要

JSX
// HTMLでは省略可能だが、JSXでは必須
<img src="image.jpg" alt="説明" />
<input type="text" />
<br />

5. イベントハンドラはキャメルケース

JSX
// HTML: onclick
// JSX: onClick
<button onClick={handleClick}>クリック</button>

5. コンポーネントの基本

Reactでは、UIを再利用可能なコンポーネントに分割します。

関数コンポーネント

現在の主流は関数コンポーネントです。

JavaScript版:

JSX
// シンプルなコンポーネント
function Welcome() {
  return <h1>ようこそ!</h1>
}

// アプリで使う
function App() {
  return (
    <div>
      <Welcome />
      <Welcome />
      <Welcome />
    </div>
  )
}

TypeScript版:

TSX
// シンプルなコンポーネント
function Welcome(): JSX.Element {
  return <h1>ようこそ!</h1>
}

// または React.FC を使う方法(最近はあまり推奨されない)
const Welcome: React.FC = () => {
  return <h1>ようこそ!</h1>
}

// アプリで使う
function App(): JSX.Element {
  return (
    <div>
      <Welcome />
      <Welcome />
      <Welcome />
    </div>
  )
}

違いのポイント:

TypeScript版では戻り値の型(: JSX.Element)を明示できます。省略しても型推論されますが、明示した方が意図が明確になります。

コンポーネントの命名規則

  • 必ず大文字で始める(PascalCase)
  • 小文字で始めるとHTMLタグと判断される
JSX
// ✅ OK
function UserProfile() { ... }

// ❌ NG:HTMLの<userprofile>タグとして扱われる
function userProfile() { ... }

コンポーネントの分割

複雑なUIは小さなコンポーネントに分割しましょう。

JavaScript版:

JSX
// Header.jsx
function Header() {
  return (
    <header>
      <h1>マイサイト</h1>
      <nav>
        <a href="/">ホーム</a>
        <a href="/about">概要</a>
      </nav>
    </header>
  )
}

export default Header
JSX
// Footer.jsx
function Footer() {
  return (
    <footer>
      <p>© 2025 マイサイト</p>
    </footer>
  )
}

export default Footer
JavaScript
// App.jsx
import Header from './Header'
import Footer from './Footer'

function App() {
  return (
    <div>
      <Header />
      <main>
        <h2>メインコンテンツ</h2>
        <p>ここに本文が入ります</p>
      </main>
      <Footer />
    </div>
  )
}

export default App

TypeScript版:

TSX
// Header.tsx
function Header(): JSX.Element {
  return (
    <header>
      <h1>マイサイト</h1>
      <nav>
        <a href="/">ホーム</a>
        <a href="/about">概要</a>
      </nav>
    </header>
  )
}

export default Header
TSX
// Footer.tsx</em>
function Footer(): JSX.Element {
  return (
    <footer>
      <p>© 2025 マイサイト</p>
    </footer>
  )
}

export default Footer
TSX
// App.tsx
import Header from './Header'
import Footer from './Footer'

function App(): JSX.Element {
  return (
    <div>
      <Header />
      <main>
        <h2>メインコンテンツ</h2>
        <p>ここに本文が入ります</p>
      </main>
      <Footer />
    </div>
  )
}

export default App

実践例:プロフィールカード

JavaScript版:

JSX
// ProfileCard.jsx
function ProfileCard() {
  const user = {
    name: "山田太郎",
    age: 25,
    job: "Webデベロッパー",
    avatar: "https://via.placeholder.com/150"
  }

  return (
    <div className="profile-card">
      <img src={user.avatar} alt={user.name} />
      <h2>{user.name}</h2>
      <p>年齢: {user.age}</p>
      <p>職業: {user.job}</p>
    </div>
  )
}

export default ProfileCard

TypeScript版:

TSX
// ProfileCard.tsx

// ユーザーの型を定義
interface User {
  name: string
  age: number
  job: string
  avatar: string
}

function ProfileCard(): JSX.Element {
  const user: User = {
    name: "山田太郎",
    age: 25,
    job: "Webデベロッパー",
    avatar: "https://via.placeholder.com/150"
  }

  return (
    <div className="profile-card">
      <img src={user.avatar} alt={user.name} />
      <h2>{user.name}</h2>
      <p>年齢: {user.age}</p>
      <p>職業: {user.job}</p>
    </div>
  )
}

export default ProfileCard

違いのポイント:

TypeScript版ではinterface Userでデータ構造を定義しています。これにより、プロパティ名のタイプミスやデータ型の間違いをエディタが指摘してくれます。

より実践的なTypeScript例(型を別ファイルに分離):

TSX
// types/user.ts
export interface User {
  name: string
  age: number
  job: string
  avatar: string
}
TSX
// ProfileCard.tsx
import { User } from './types/user'

function ProfileCard(): JSX.Element {
  const user: User = {
    name: "山田太郎",
    age: 25,
    job: "Webデベロッパー",
    avatar: "https://via.placeholder.com/150"
  }

  return (
    <div className="profile-card">
      <img src={user.avatar} alt={user.name} />
      <h2>{user.name}</h2>
      <p>年齢: {user.age}</p>
      <p>職業: {user.job}</p>
    </div>
  )
}

export default ProfileCard

対応するCSS(App.cssまたはindex.css):

CSS
.profile-card {
  border: 1px solid #ddd;
  border-radius: 8px;
  padding: 20px;
  max-width: 300px;
  text-align: center;
  box-shadow: 0 2px 4px rgba(0,0,0,0.1);
}

.profile-card img {
  border-radius: 50%;
  width: 150px;
  height: 150px;
}

.profile-card h2 {
  margin: 10px 0;
}

.profile-card p {
  color: #666;
  margin: 5px 0;
}

JavaScriptとTypeScriptの使い分け

JavaScriptを選ぶ場合

  • 小規模なプロジェクト
  • プロトタイプやMVPの素早い開発
  • TypeScriptの学習コストを避けたい
  • チームメンバーがTypeScriptに不慣れ

TypeScriptを選ぶ場合(推奨)

  • 中〜大規模プロジェクト
  • 長期的にメンテナンスするアプリ
  • チーム開発
  • バグを早期発見したい
  • エディタの補完機能を最大限活用したい

初心者へのアドバイス:

最初はJavaScriptで学習し、Reactの基本概念を理解してからTypeScriptに移行するのも良い選択肢です。ただし、最近の開発現場ではTypeScriptが標準になりつつあるため、早めに慣れておくと就職・転職に有利です。

まとめ

この記事では、ReactとTypeScriptの基礎を学びました。

学んだこと:

  • Reactはコンポーネントベースのライブラリ
  • TypeScriptは型安全性を提供し、大規模開発に適している
  • Viteで簡単にプロジェクトを作成できる
  • JSX/TSXでJavaScriptの中にHTMLを書ける
  • 関数コンポーネントでUIを作る
  • コンポーネントを分割して再利用する
  • TypeScriptでは型定義により安全性が向上する

JavaScriptとTypeScriptの主な違い:

  • ファイル拡張子:.jsx vs .tsx
  • 型注釈の有無
  • interfacetypeによる型定義
  • より強力なエディタサポート

次のステップ:
次回は、propsを使ってコンポーネント間でデータを受け渡す方法や、useStateを使った状態管理について学びます。TypeScriptでのpropsの型定義も併せて解説します。これらをマスターすると、より動的で安全なアプリケーションが作れるようになります。

まずは今回学んだ内容を実際にコードを書いて試してみましょう。JavaScriptとTypeScript、どちらから始めても構いません。エラーが出ても恐れずに、いろいろ実験してみることが上達の近道です!