ReactとHTMLの違いとは?JSXの基本を分かりやすく解説
ReactとHTMLの違いからJSXの基本的な書き方まで初心者向けに解説。実際のコード例とともに、HTMLからReactへの移行方法を詳しく説明します。
みなさん、Reactを学び始めていますか?
「HTMLは書けるけど、Reactって何が違うの?」「JSXって何?HTMLとどう違うの?」と思ったことはありませんか?
この記事では、ReactとHTMLの基本的な違いからJSXの書き方まで、初心者向けに分かりやすく解説します。 実際のコード例を見ながら、HTMLからReactにスムーズに移行するコツを一緒に学んでいきましょう。
ReactとHTMLって何が違うの?
まずは、ReactとHTMLの根本的な違いを理解しましょう。
HTMLの特徴
HTMLは静的なマークアップ言語です。 一度書いたら、内容は変わりません。
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<title>マイページ</title>
</head>
<body>
<h1>こんにちは、田中さん</h1>
<p>今日の天気は晴れです</p>
<button onclick="showMessage()">クリック</button>
<script>
function showMessage() {
alert('ボタンがクリックされました!');
}
</script>
</body>
</html>
このHTMLでは、「田中さん」と「晴れ」は固定されています。 変更したい場合は、HTMLファイル自体を書き換える必要があります。
Reactの特徴
Reactは動的なJavaScriptライブラリです。 データが変わると、自動的に表示も更新されます。
import React, { useState } from 'react';
function MyPage() {
const [userName] = useState('田中さん');
const [weather] = useState('晴れ');
const [message, setMessage] = useState('');
const showMessage = () => {
setMessage('ボタンがクリックされました!');
};
return (
<div>
<h1>こんにちは、{userName}</h1>
<p>今日の天気は{weather}です</p>
<button onClick={showMessage}>クリック</button>
{message && <p>{message}</p>}
</div>
);
}
Reactでは、{userName}
や{weather}
のように変数を使えます。
データが変わると、画面も自動で更新されるんです。
主な違いをまとめると
HTMLとReactの違いはこんな感じです:
HTML
- 静的な構造定義
- 固定された内容
- ファイル単位での管理
- シンプルな学習コスト
React
- 動的なコンポーネント
- 状態に応じた表示変更
- コンポーネント単位での管理
- 再利用可能な部品
簡単に言うと、HTMLは「設計図」で、Reactは「動く機械」のようなイメージです。
JSXって何だろう?
JSXは、JavaScriptの中でHTMLのような記法が使える構文拡張です。
JSXの基本的な書き方
// 基本的なJSX
const element = <h1>Hello, World!</h1>;
// JavaScriptの変数を埋め込み
const name = '田中太郎';
const greeting = <h1>こんにちは、{name}さん!</h1>;
// 複数の要素
const content = (
<div>
<h1>タイトル</h1>
<p>これは段落です。</p>
</div>
);
{}
の中にJavaScriptの式を書くことで、動的な値を表示できます。
HTMLからJSXへの変換例
実際にHTMLからJSXに変換してみましょう:
HTML版
<div class="card">
<img src="profile.jpg" alt="プロフィール画像">
<h2>田中太郎</h2>
<p>Webデベロッパー</p>
<button onclick="showDetails()">詳細を見る</button>
</div>
JSX版
function ProfileCard() {
const name = '田中太郎';
const job = 'Webデベロッパー';
const showDetails = () => {
alert('詳細を表示します');
};
return (
<div className="card">
<img src="profile.jpg" alt="プロフィール画像" />
<h2>{name}</h2>
<p>{job}</p>
<button onClick={showDetails}>詳細を見る</button>
</div>
);
}
JSXでは、変数を{}
で囲んで表示できます。
これで、name
やjob
の値を変えれば、自動で表示も変わります。
JSXの便利な機能
1. JavaScript式の埋め込み
function UserInfo({ user }) {
return (
<div>
<h1>{user.name}</h1>
<p>年齢: {user.age}歳</p>
<p>職業: {user.job || '未設定'}</p>
<p>今日は{new Date().toLocaleDateString()}です</p>
</div>
);
}
計算結果や関数の戻り値も表示できます。
2. 条件分岐
function WelcomeMessage({ user }) {
return (
<div>
{user ? (
<h1>おかえりなさい、{user.name}さん!</h1>
) : (
<h1>ログインしてください</h1>
)}
</div>
);
}
ユーザーがログインしているかどうかで、表示を切り替えられます。
3. 配列の表示
function TodoList({ todos }) {
return (
<ul>
{todos.map((todo, index) => (
<li key={index}>{todo}</li>
))}
</ul>
);
}
配列のデータを繰り返し表示するのも簡単です。
HTMLからJSXに変換するルール
HTMLをJSXに変換する時の重要なルールを覚えましょう。
属性名が変わる
HTMLとJSXでは、一部の属性名が異なります:
// HTML → JSX
class → className
for → htmlFor
onclick → onClick
onchange → onChange
tabindex → tabIndex
実際の例を見てみましょう:
// HTML
<div class="container">
<label for="email">メール</label>
<input id="email" onchange="handleChange()">
</div>
// JSX
<div className="container">
<label htmlFor="email">メール</label>
<input id="email" onChange={handleChange} />
</div>
class
はclassName
に、for
はhtmlFor
に変わります。
自己終了タグが必須
HTMLでは省略できた自己終了タグが、JSXでは必須になります:
// HTML(自己終了タグは任意)
<img src="image.jpg" alt="画像">
<input type="text" name="username">
<br>
<hr>
// JSX(自己終了タグは必須)
<img src="image.jpg" alt="画像" />
<input type="text" name="username" />
<br />
<hr />
/>
を忘れずに付けましょう。
単一のルート要素
JSXでは、必ず一つの要素で囲む必要があります:
// ❌ NG: 複数のルート要素
return (
<h1>タイトル</h1>
<p>段落</p>
);
// ✅ OK: 単一要素で囲む
return (
<div>
<h1>タイトル</h1>
<p>段落</p>
</div>
);
// ✅ OK: React Fragment使用
return (
<>
<h1>タイトル</h1>
<p>段落</p>
</>
);
余計なdiv
を作りたくない場合は、<></>
(Fragment)を使いましょう。
スタイルの書き方
インラインスタイルの書き方も変わります:
// HTML
<div style="background-color: red; font-size: 16px;">
スタイル付きテキスト
</div>
// JSX
<div style={{
backgroundColor: 'red',
fontSize: '16px'
}}>
スタイル付きテキスト
</div>
JSXでは、スタイルをオブジェクトとして書きます。
ケバブケース(background-color
)はキャメルケース(backgroundColor
)に変わります。
実践!HTMLをReactに変換してみよう
実際のHTMLページをReactコンポーネントに変換してみましょう。
プロフィールカードを作る
元のHTML
<!DOCTYPE html>
<html>
<head>
<title>プロフィール</title>
<style>
.profile-card {
border: 1px solid #ddd;
border-radius: 8px;
padding: 20px;
max-width: 300px;
text-align: center;
}
.avatar {
width: 100px;
height: 100px;
border-radius: 50%;
}
.follow-btn {
background-color: #007bff;
color: white;
border: none;
padding: 10px 20px;
border-radius: 4px;
cursor: pointer;
}
</style>
</head>
<body>
<div class="profile-card">
<img class="avatar" src="avatar.jpg" alt="アバター">
<h2>田中太郎</h2>
<p>フロントエンドデベロッパー</p>
<p>フォロワー: <span id="follower-count">1,234</span>人</p>
<button class="follow-btn" onclick="toggleFollow()">
フォローする
</button>
</div>
<script>
let isFollowing = false;
let followerCount = 1234;
function toggleFollow() {
const button = document.querySelector('.follow-btn');
const countElement = document.getElementById('follower-count');
if (isFollowing) {
isFollowing = false;
followerCount--;
button.textContent = 'フォローする';
button.style.backgroundColor = '#007bff';
} else {
isFollowing = true;
followerCount++;
button.textContent = 'フォロー中';
button.style.backgroundColor = '#28a745';
}
countElement.textContent = followerCount.toLocaleString();
}
</script>
</body>
</html>
Reactに変換
import React, { useState } from 'react';
import './ProfileCard.css';
function ProfileCard({ user }) {
const [isFollowing, setIsFollowing] = useState(false);
const [followerCount, setFollowerCount] = useState(user.followers);
const toggleFollow = () => {
if (isFollowing) {
setIsFollowing(false);
setFollowerCount(prev => prev - 1);
} else {
setIsFollowing(true);
setFollowerCount(prev => prev + 1);
}
};
return (
<div className="profile-card">
<img
className="avatar"
src={user.avatar}
alt={`${user.name}のアバター`}
/>
<h2>{user.name}</h2>
<p>{user.job}</p>
<p>
フォロワー: <span>{followerCount.toLocaleString()}</span>人
</p>
<button
className={`follow-btn ${isFollowing ? 'following' : ''}`}
onClick={toggleFollow}
>
{isFollowing ? 'フォロー中' : 'フォローする'}
</button>
</div>
);
}
function App() {
const userData = {
name: '田中太郎',
job: 'フロントエンドデベロッパー',
avatar: 'avatar.jpg',
followers: 1234
};
return (
<div>
<h1>プロフィール</h1>
<ProfileCard user={userData} />
</div>
);
}
export default App;
HTMLでは直接DOMを操作していましたが、ReactではuseState
を使って状態を管理します。
これで、データが変わると自動で画面も更新されます。
フォームの変換例
元のHTML
<form onsubmit="handleSubmit(event)">
<div>
<label for="name">名前:</label>
<input type="text" id="name" name="name" required>
</div>
<div>
<label for="email">メール:</label>
<input type="email" id="email" name="email" required>
</div>
<button type="submit">送信</button>
</form>
<script>
function handleSubmit(event) {
event.preventDefault();
const formData = new FormData(event.target);
const data = Object.fromEntries(formData);
console.log('送信データ:', data);
alert('送信完了!');
}
</script>
Reactに変換
import React, { useState } from 'react';
function ContactForm() {
const [formData, setFormData] = useState({
name: '',
email: ''
});
const [errors, setErrors] = useState({});
const handleChange = (e) => {
const { name, value } = e.target;
setFormData(prev => ({
...prev,
[name]: value
}));
if (errors[name]) {
setErrors(prev => ({
...prev,
[name]: ''
}));
}
};
const validateForm = () => {
const newErrors = {};
if (!formData.name.trim()) {
newErrors.name = '名前は必須です';
}
if (!formData.email.trim()) {
newErrors.email = 'メールアドレスは必須です';
} else if (!/\S+@\S+\.\S+/.test(formData.email)) {
newErrors.email = 'メールアドレスの形式が正しくありません';
}
return newErrors;
};
const handleSubmit = (e) => {
e.preventDefault();
const newErrors = validateForm();
if (Object.keys(newErrors).length > 0) {
setErrors(newErrors);
return;
}
console.log('送信データ:', formData);
alert('送信完了!');
setFormData({ name: '', email: '' });
};
return (
<form onSubmit={handleSubmit}>
<div>
<label htmlFor="name">名前:</label>
<input
type="text"
id="name"
name="name"
value={formData.name}
onChange={handleChange}
required
/>
{errors.name && <span className="error">{errors.name}</span>}
</div>
<div>
<label htmlFor="email">メール:</label>
<input
type="email"
id="email"
name="email"
value={formData.email}
onChange={handleChange}
required
/>
{errors.email && <span className="error">{errors.email}</span>}
</div>
<button type="submit">送信</button>
</form>
);
}
export default ContactForm;
Reactでは、フォームの値をstate
で管理します。
バリデーション結果もリアルタイムで表示できるので、ユーザーにとって使いやすいフォームになります。
コンポーネント化のメリット
HTMLをReactに変換する時の最大のメリットはコンポーネント化です。
繰り返し部分をコンポーネント化
HTML(繰り返しコード)
<div class="product-list">
<div class="product-item">
<img src="product1.jpg" alt="商品1">
<h3>商品1</h3>
<p>¥1,000</p>
<button onclick="addToCart(1)">カートに追加</button>
</div>
<div class="product-item">
<img src="product2.jpg" alt="商品2">
<h3>商品2</h3>
<p>¥2,000</p>
<button onclick="addToCart(2)">カートに追加</button>
</div>
<div class="product-item">
<img src="product3.jpg" alt="商品3">
<h3>商品3</h3>
<p>¥3,000</p>
<button onclick="addToCart(3)">カートに追加</button>
</div>
</div>
React(コンポーネント化)
function ProductItem({ product, onAddToCart }) {
return (
<div className="product-item">
<img src={product.image} alt={product.name} />
<h3>{product.name}</h3>
<p>¥{product.price.toLocaleString()}</p>
<button onClick={() => onAddToCart(product.id)}>
カートに追加
</button>
</div>
);
}
function ProductList({ products, onAddToCart }) {
return (
<div className="product-list">
{products.map(product => (
<ProductItem
key={product.id}
product={product}
onAddToCart={onAddToCart}
/>
))}
</div>
);
}
function App() {
const products = [
{ id: 1, name: '商品1', price: 1000, image: 'product1.jpg' },
{ id: 2, name: '商品2', price: 2000, image: 'product2.jpg' },
{ id: 3, name: '商品3', price: 3000, image: 'product3.jpg' }
];
const handleAddToCart = (productId) => {
console.log(`商品ID: ${productId} をカートに追加しました`);
};
return (
<div>
<h1>商品一覧</h1>
<ProductList products={products} onAddToCart={handleAddToCart} />
</div>
);
}
コンポーネント化することで、同じコードを何度も書く必要がなくなります。 商品が100個あっても、配列にデータを追加するだけで済みます。
よくある間違いと対処法
HTMLからReactに移行する時によくある間違いを見てみましょう。
1. クラス名の間違い
// ❌ NG: HTMLの書き方
<div class="container">
<p>テキスト</p>
</div>
// ✅ OK: JSXの書き方
<div className="container">
<p>テキスト</p>
</div>
class
はclassName
に変更しましょう。
2. イベントハンドラーの間違い
// ❌ NG: 文字列での指定
<button onclick="handleClick()">クリック</button>
// ✅ OK: 関数での指定
<button onClick={handleClick}>クリック</button>
// ✅ OK: 無名関数での指定
<button onClick={() => handleClick('引数')}>クリック</button>
イベントハンドラーは関数として渡しましょう。
3. 自己終了タグの忘れ
// ❌ NG: 終了タグなし
<img src="image.jpg" alt="画像">
<input type="text">
// ✅ OK: 自己終了タグ
<img src="image.jpg" alt="画像" />
<input type="text" />
JSXでは自己終了タグが必須です。
4. 状態管理の間違い
// ❌ NG: 直接的な値の変更
function Counter() {
let count = 0;
const increment = () => {
count = count + 1; // 画面が更新されない
};
return (
<div>
<p>カウント: {count}</p>
<button onClick={increment}>増加</button>
</div>
);
}
// ✅ OK: useStateを使用
function Counter() {
const [count, setCount] = useState(0);
const increment = () => {
setCount(count + 1); // 正しく画面が更新される
};
return (
<div>
<p>カウント: {count}</p>
<button onClick={increment}>増加</button>
</div>
);
}
値を変更する時は、必ずuseState
を使いましょう。
まとめ
HTMLとReactの違いから、JSXの基本的な書き方まで詳しく学習しました。
覚えておきたいポイント
- HTMLは静的、Reactは動的
- JSXでは
{}
内にJavaScript式を書ける - 属性名が一部変わる(
class
→className
など) - 自己終了タグが必須
- 状態管理は
useState
を使う
HTMLからReactへの移行手順
- 属性名を変更する
- 自己終了タグを追加する
- 単一要素で囲む
- 動的な部分を変数にする
- 状態管理を
useState
で行う
HTMLの知識があれば、Reactへの移行はそれほど難しくありません。 ぜひ実際にコードを書いて、JSXの書き方に慣れていってくださいね!