JSX で記事リストをレンダリング
この章では、JSX 式を使って JS データを UI にレンダリングし、ブログのホームページに記事カードのリストを表示できるようになります。
{} で JSX に式を埋め込む
JSX では、波括弧 {}は JavaScript の世界への入り口です。
任意の JS 式を波括弧の中に置けます:変数、演算、関数呼び出し、三項演算式などです。
実例
const blogTitle = 'サンプル 前端笔记'
const author = '小明'
return (
<div>
<h1>{blogTitle}</h1>
<p>著者:{author}</p>
<p>現在時刻:{new Date().toLocaleDateString()}</p>
<p>ようこそメッセージ:{author ?`你好,${author}` : '欢迎访客'}</p>
</div>
)
}
ページには以下のように表示されます:
サンプル 前端笔记 作者:小明 当前时间:2024/5/15 欢迎语:你好,小明
波括弧の中に置けるのは式(値を計算できるコード)であり、文は置けません。例えば
{if (condition) ...}不正ですが、{condition ? 'A' : 'B'}合法です。
属性バインディング
HTML 属性は JSX では波括弧を使って動的にバインドする必要があります。
実例
const coverUrl = '/images/react-cover.png'
const linkUrl = '/post/1'
return (
<div>
{/* 动态属性:花括号绑定 JS 变量 */}
<img src={coverUrl} alt=記事カバー />
<a href={linkUrl}>続きを読む</a>
{/* 注意:class 要写成 className */}
<div className="card active">カードの内容</div>
{/* style はオブジェクトを受け取り、プロパティ名はキャメルケースです */}
<div style={{ color: '#427DB8', fontSize: '16px' }}>
緑色の文字
</div>
</div>
)
}
| HTML | JSX | 説明 |
|---|---|---|
class="btn" | className="btn" | class は JS の予約語です |
style="color: red" | style={{ color: 'red' }} | オブジェクトを受け取り、プロパティ名はキャメルケース |
src="xxx.html" | src={variable} | 動的な値は波括弧を使う |
onclick="fn()" | onClick={fn} | イベント名はキャメルケース、関数の参照を渡す |
リストレンダリング:array.map()
React には Vue のようにv-forそのようなディレクティブはありません。
JSX でリストをレンダリングするには、JavaScript のarray.map()メソッドを使います。
実例
// JS オブジェクト配列で記事データをシミュレートする
const articles = [
{
id: 1,
title: 'React 入门完全指南',
summary: 'ゼロから React Hooks を学び、useState、useEffect などの核心概念をカバーします。',
date: '2024-05-10',
category: 'React',
cover: '/images/react.png'
},
{
id: 2,
title: 'JavaScript 异步编程详解',
summary: '一文で Promise、async/await、イベントループとマイクロタスクキューを理解する。',
date: '2024-05-08',
category: 'JavaScript',
cover: '/images/js.png'
},
{
id: 3,
title: 'CSS Grid 布局实战',
summary: 'CSS Grid を使用して、複雑なレスポンシブレイアウトを簡単に実現します。',
date: '2024-05-05',
category: 'CSS',
cover: '/images/css.png'
}
]
return (
<div className="article-list">
{/* map 遍历数组,每条数据返回一段 JSX */}
{articles.map(article => (
<div key={article.id} className="card">
<img src={article.cover} alt={article.title} />
<div className="card-body">
<span className="category">{article.category}</span>
<h3>{article.title}</h3>
<p>{article.summary}</p>
<span className="date">{article.date}</span>
</div>
</div>
))}
</div>
)
}
key 属性の重要性
keyこれはリスト内の各要素に割り当てられる一意の識別子で、React がどの要素が変更されたかを認識するのに役立ちます。
key がない場合、React は「インプレース更新」戦略を採用するため、状態が混乱したりパフォーマンスが低下したりする可能性があります。
| key の値 | 結果 |
|---|---|
| 一意の id(推奨) | 各要素を正しく追跡し、効率的な Diff |
| 配列のインデックス index | 挿入/削除時に入力欄の内容が乱れる可能性があります |
| key を書かない | コンソール警告、パフォーマンス低下 |
常に map が返す JSX に一意で安定したkey を付けましょう。特にリスト項目が追加・削除・並べ替えされる可能性がある場合は、index を key に使わないでください。
条件レンダリング
React には v-if はありませんが、条件レンダリングを実現する方法が3つあります。
実例
const articles = []
const isLoading = false
return (
<div>
{/* 方式一:三元表达式 — 适合二选一 */}
{isLoading ? (
<p>読み込み中、お待ちください...</p>
) : (
<p>読み込み完了!</p>
)}
{/* 方式二:&& 短路 — 适合「有条件就显示,没条件就不显示」 */}
{articles.length === 0 && <p>まだ記事がありません。お楽しみに。</p>}
{/* 方式3:if/else をコンポーネントのトップレベルで — 複雑な多条件ロジックに適している */}
{articles.length > 0 ? (
<div>
{articles.map(a => <div key={a.id}>{a.title}</div>)}
</div>
) : (
<p>データがありません</p>
)}
</div>
)
}
3つの条件レンダリング方法の比較
| 方式 | 書き方 | 適用シーン |
|---|---|---|
三項演算子? : | {cond ? <A /> : <B />} | 二者択一で、必ず何かを返す必要がある |
短絡&& | {cond && <A />} | あれば表示し、なければ表示しない |
| 事前の if 判定 | return の前に変数に JSX を格納しておく | 条件分岐が複雑な場合 |
&&短絡には落とし穴があります:条件が数値 0 の場合、"0" がレンダリングされます。推奨は&&左側は常にブール値にすること:{list.length > 0 && ...}ではなく{list.length && ...}。
実践:完全版ブログホームページ
実例
import './App.css'
function App() {
const articles = [
{
id: 1, title: 'React 入门完全指南',
summary: 'ゼロから React Hooks を学び、useState、useEffect などの核心概念をカバーします。',
date: '2024-05-10', category: 'React', cover: '/images/react.png'
},
{
id: 2, title: 'JavaScript 异步编程详解',
summary: '一文で Promise、async/await、イベントループとマイクロタスクキューを理解する。',
date: '2024-05-08', category: 'JavaScript', cover: '/images/js.png'
},
{
id: 3, title: 'CSS Grid 布局实战',
summary: 'CSS Grid を使用して、複雑なレスポンシブレイアウトを簡単に実現します。',
date: '2024-05-05', category: 'CSS', cover: '/images/css.png'
}
]
return (
<div className="app">
<header className="navbar">
<h1 className="logo">サンプル Blog</h1>
<nav>
<a href="/">ホーム</a>
<a href="#">このサイトについて</a>
</nav>
</header>
<main className="container">
<h2 className="section-title">最新記事</h2>
{/* 条件渲染:有文章就显示,没文章就显示空态 */}
{articles.length === 0 ? (
<p className="empty-tip">まだ記事がありません。お楽しみに。</p>
) : (
<div className="article-grid">
{/* 列表渲染:map 遍历数组 */}
{articles.map(article => (
<div key={article.id} className="article-card">
<img src={article.cover} alt={article.title} className="card-cover" />
<div className="card-content">
<span className="card-category">{article.category}</span>
<h3 className="card-title">{article.title}</h3>
<p className="card-summary">{article.summary}</p>
<span className="card-date">{article.date}</span>
</div>
</div>
))}
</div>
)}
</main>
<footer className="footer">
<p>© 2024 サンプル Blog. Powered by React.</p>
</footer>
</div>
)
}
export default App
実例
.section-title {
font-size: 24px;
margin-bottom: 20px;
color: #333;
}
.article-grid {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
gap: 24px;
}
.article-card {
background: #fff;
border-radius: 12px;
overflow: hidden;
box-shadow: 0 2px 12px rgba(0,0,0,0.08);
transition: transform 0.2s, box-shadow 0.2s;
cursor: pointer;
}
.article-card:hover {
transform: translateY(-4px);
box-shadow: 0 8px 24px rgba(0,0,0,0.12);
}
.card-cover {
width: 100%;
height: 180px;
object-fit: cover;
}
.card-content {
padding: 16px;
}
.card-category {
display: inline-block;
padding: 2px 10px;
background: #e3f2fd;
color: #1976d2;
border-radius: 12px;
font-size: 12px;
margin-bottom: 8px;
}
.card-title {
font-size: 18px;
margin-bottom: 8px;
color: #222;
}
.card-summary {
font-size: 14px;
color: #666;
line-height: 1.6;
margin-bottom: 12px;
}
.card-date {
font-size: 12px;
color: #999;
}
.empty-tip {
text-align: center;
color: #999;
padding: 60px 0;
font-size: 16px;
}
本章のまとめ
この章では、JSX の4つの基本的な操作を学びました:{}式の埋め込み、属性バインディング(className / style)、map()リストレンダリング + key、条件レンダリング(三項演算子 / 短絡)。
これで、ブログのホームページは JS データに基づいて記事カードを動的にレンダリングできるようになりました。
その他の拡張