React CDNで始める|インストール不要の超簡単スタート方法
React CDNを使ってインストール不要でReactを始める方法を詳しく解説。HTMLファイル1つで即座にReact開発をスタートできます。
みなさん、Reactを始めたいと思ったことはありませんか?
「環境構築が面倒そう」 「Node.jsとかよくわからない」 「とりあえず触ってみたい」
そんな風に思ったことはありませんか?
実は、HTMLファイル1つでReactを始めることができるんです。 この記事では、CDNを使った超簡単なReactの始め方を詳しく解説します。
複雑な設定は一切不要! 今すぐにReactの世界に飛び込んでいきましょう。
CDNって何?なぜReactが簡単に始められるの?
まず、CDNの基本的な考え方を理解しましょう。
CDNの基本概念
CDNは、Content Delivery Networkの略です。 簡単に言うと、「インターネット上からライブラリを借りてくる」という感じです。
通常のReact開発では、こんな作業が必要です。
- Node.jsのインストール
- npmのセットアップ
- create-react-appの実行
- 複雑なフォルダ構成の理解
でも、CDNを使えば、これらの作業が一切不要になります。
CDNの特徴
CDNには、こんな特徴があります。
- インストール不要: 何もダウンロードしなくてOK
- 即座に開始: HTMLファイルを作るだけで始められる
- 軽量: 必要最小限のファイルだけを使用
- 学習に最適: 複雑な設定なしでReactの基本を理解
「難しそう...」と思うかもしれませんが、実は数分で完了します。
CDNが適している場面
CDNは、こんな場面で特に有効です。
- Reactの学習: 基本概念を理解したい初心者
- プロトタイプ作成: アイデアを素早く形にしたい
- 既存サイトの改善: 一部分だけReactを使いたい
- 教育現場: 授業やワークショップでの活用
心配いりません! 一つずつ丁寧に説明していきます。
最初のHello World
では、実際にReactアプリを作ってみましょう。
基本的なHTMLファイルの作成
まず、この内容でHTMLファイルを作成してください。
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>React CDN サンプル</title>
</head>
<body>
<div id="root"></div>
<!-- React CDN -->
<script crossorigin src="https://unpkg.com/react@18/umd/react.development.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@18/umd/react-dom.development.js"></script>
<!-- Babel CDN -->
<script src="https://unpkg.com/@babel/standalone/babel.min.js"></script>
<!-- Reactアプリケーション -->
<script type="text/babel">
function App() {
return (
<div>
<h1>Hello, React!</h1>
<p>CDNを使ってReactを始めました!</p>
</div>
);
}
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(<App />);
</script>
</body>
</html>
このファイルをブラウザで開いてみてください。 「Hello, React!」と表示されるはずです。
すごいですよね! たったこれだけで、Reactアプリが動いています。
コードの詳細解説
では、各部分が何をしているか見てみましょう。
1. React本体の読み込み
<script crossorigin src="https://unpkg.com/react@18/umd/react.development.js"></script>
これは、React本体を読み込んでいます。
crossorigin
属性は、セキュリティのために必要です。
2. ReactDOMの読み込み
<script crossorigin src="https://unpkg.com/react-dom@18/umd/react-dom.development.js"></script>
ReactDOMは、ReactコンポーネントをブラウザのDOMに表示するためのライブラリです。 Reactだけでは、ブラウザに表示できないんです。
3. Babelの読み込み
<script src="https://unpkg.com/@babel/standalone/babel.min.js"></script>
Babelは、JSXをJavaScriptに変換してくれるツールです。 ブラウザはJSXを理解できないので、Babelが必要になります。
4. Reactアプリケーション
<script type="text/babel">
function App() {
return (
<div>
<h1>Hello, React!</h1>
<p>CDNを使ってReactを始めました!</p>
</div>
);
}
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(<App />);
</script>
type="text/babel"
に注目してください。
これにより、Babelがこのスクリプトを処理してくれます。
App
関数は、Reactコンポーネントです。
HTMLっぽい書き方(JSX)でUIを定義しています。
最後の2行で、作成したコンポーネントをブラウザに表示しています。
実際に動かしてみよう
このHTMLファイルをブラウザで開くと、こんな感じになります。
- ブラウザがHTMLを読み込む
- Reactライブラリが読み込まれる
- BabelがJSXをJavaScriptに変換
- Reactコンポーネントが表示される
「本当にこれだけで動くの?」と思うかもしれませんが、実際に試してみてください。
きっと驚くと思います!
実用的なカウンターアプリを作ってみよう
Hello Worldができたので、次はもう少し実用的なアプリを作ってみましょう。
インタラクティブなカウンター
ボタンを押すと数字が変わるカウンターアプリを作ってみます。
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Reactカウンター</title>
<style>
body {
font-family: Arial, sans-serif;
max-width: 600px;
margin: 0 auto;
padding: 20px;
}
.counter {
text-align: center;
padding: 20px;
border: 2px solid #007bff;
border-radius: 10px;
margin: 20px 0;
}
.count {
font-size: 48px;
font-weight: bold;
color: #007bff;
margin: 20px 0;
}
button {
font-size: 18px;
padding: 10px 20px;
margin: 0 10px;
border: none;
border-radius: 5px;
cursor: pointer;
}
.increment {
background-color: #28a745;
color: white;
}
.decrement {
background-color: #dc3545;
color: white;
}
.reset {
background-color: #6c757d;
color: white;
}
</style>
</head>
<body>
<div id="root"></div>
<script crossorigin src="https://unpkg.com/react@18/umd/react.development.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@18/umd/react-dom.development.js"></script>
<script src="https://unpkg.com/@babel/standalone/babel.min.js"></script>
<script type="text/babel">
function Counter() {
const [count, setCount] = React.useState(0);
const increment = () => {
setCount(count + 1);
};
const decrement = () => {
setCount(count - 1);
};
const reset = () => {
setCount(0);
};
return (
<div className="counter">
<h1>Reactカウンター</h1>
<div className="count">{count}</div>
<div>
<button className="increment" onClick={increment}>
+1
</button>
<button className="decrement" onClick={decrement}>
-1
</button>
<button className="reset" onClick={reset}>
リセット
</button>
</div>
</div>
);
}
function App() {
return (
<div>
<h1>React CDN サンプルアプリ</h1>
<Counter />
</div>
);
}
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(<App />);
</script>
</body>
</html>
このコードを実行すると、数字が表示されて、ボタンを押すと数字が変わります。
すごいですよね! たったこれだけで、動的なWebアプリが作れました。
カウンターアプリの詳細解説
では、新しく出てきた部分を詳しく見てみましょう。
useState Hook
const [count, setCount] = React.useState(0);
これは、useState Hookと呼ばれるReactの機能です。
count
は現在の数値を保持しています。
setCount
は数値を変更するための関数です。
0
は初期値です。
イベントハンドラー
const increment = () => {
setCount(count + 1);
};
これは、イベントハンドラーと呼ばれる関数です。 ボタンがクリックされたときに実行されます。
setCount(count + 1)
で、現在の数値に1を足しています。
JSXでのイベント処理
<button className="increment" onClick={increment}>
+1
</button>
onClick={increment}
で、ボタンがクリックされたときにincrement
関数を実行します。
HTMLのonclick
とは少し書き方が違いますが、やっていることは同じです。
実際に動かしてみよう
このファイルをブラウザで開いて、ボタンをクリックしてみてください。
- +1ボタン: 数字が1増える
- -1ボタン: 数字が1減る
- リセットボタン: 数字が0になる
「こんなに簡単にできるの?」と思うかもしれませんが、本当にこれだけです。
Reactの力を実感できたでしょうか?
もう少し複雑なToDoリストを作ってみよう
カウンターの次は、ToDoリストを作ってみましょう。
基本的なToDoリスト
タスクを追加・削除・完了マークできるToDoリストを作ります。
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>React ToDoリスト</title>
<style>
body {
font-family: Arial, sans-serif;
max-width: 600px;
margin: 0 auto;
padding: 20px;
background-color: #f5f5f5;
}
.todo-app {
background: white;
border-radius: 10px;
padding: 20px;
box-shadow: 0 2px 10px rgba(0,0,0,0.1);
}
.todo-input {
display: flex;
margin-bottom: 20px;
}
.todo-input input {
flex: 1;
padding: 10px;
font-size: 16px;
border: 2px solid #ddd;
border-radius: 5px 0 0 5px;
border-right: none;
}
.todo-input button {
padding: 10px 20px;
font-size: 16px;
background-color: #007bff;
color: white;
border: 2px solid #007bff;
border-radius: 0 5px 5px 0;
cursor: pointer;
}
.todo-item {
display: flex;
align-items: center;
padding: 10px;
border-bottom: 1px solid #eee;
}
.todo-item.completed {
opacity: 0.6;
text-decoration: line-through;
}
.todo-item input[type="checkbox"] {
margin-right: 10px;
}
.todo-text {
flex: 1;
}
.delete-btn {
background-color: #dc3545;
color: white;
border: none;
padding: 5px 10px;
border-radius: 3px;
cursor: pointer;
}
</style>
</head>
<body>
<div id="root"></div>
<script crossorigin src="https://unpkg.com/react@18/umd/react.development.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@18/umd/react-dom.development.js"></script>
<script src="https://unpkg.com/@babel/standalone/babel.min.js"></script>
<script type="text/babel">
function TodoApp() {
const [todos, setTodos] = React.useState([]);
const [inputValue, setInputValue] = React.useState('');
const addTodo = () => {
if (inputValue.trim() !== '') {
const newTodo = {
id: Date.now(),
text: inputValue.trim(),
completed: false
};
setTodos([...todos, newTodo]);
setInputValue('');
}
};
const deleteTodo = (id) => {
setTodos(todos.filter(todo => todo.id !== id));
};
const toggleTodo = (id) => {
setTodos(todos.map(todo =>
todo.id === id
? { ...todo, completed: !todo.completed }
: todo
));
};
const handleKeyPress = (e) => {
if (e.key === 'Enter') {
addTodo();
}
};
return (
<div className="todo-app">
<h1>React ToDoリスト</h1>
<div className="todo-input">
<input
type="text"
value={inputValue}
onChange={(e) => setInputValue(e.target.value)}
onKeyPress={handleKeyPress}
placeholder="新しいタスクを入力..."
/>
<button onClick={addTodo}>追加</button>
</div>
<div className="todo-list">
{todos.length === 0 ? (
<p>タスクがありません。新しいタスクを追加してください。</p>
) : (
todos.map(todo => (
<div
key={todo.id}
className={`todo-item ${todo.completed ? 'completed' : ''}`}
>
<input
type="checkbox"
checked={todo.completed}
onChange={() => toggleTodo(todo.id)}
/>
<span className="todo-text">{todo.text}</span>
<button
className="delete-btn"
onClick={() => deleteTodo(todo.id)}
>
削除
</button>
</div>
))
)}
</div>
<div style={{ marginTop: '20px', color: '#666' }}>
<p>完了: {todos.filter(todo => todo.completed).length} / 全体: {todos.length}</p>
</div>
</div>
);
}
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(<TodoApp />);
</script>
</body>
</html>
このコードを実行すると、本格的なToDoリストが完成します。
ちょっと長いですが、大丈夫です! 一つずつ見ていきましょう。
ToDoリストの詳細解説
新しく出てきた概念を詳しく解説します。
配列の状態管理
const [todos, setTodos] = React.useState([]);
todos
は、タスクの配列を保持しています。
最初は空の配列[]
から始まります。
タスクの追加
const addTodo = () => {
if (inputValue.trim() !== '') {
const newTodo = {
id: Date.now(),
text: inputValue.trim(),
completed: false
};
setTodos([...todos, newTodo]);
setInputValue('');
}
};
newTodo
というオブジェクトを作成しています。
Date.now()
で一意のIDを生成しています。
[...todos, newTodo]
で、既存の配列に新しいタスクを追加しています。
これをスプレッド演算子と呼びます。
タスクの削除
const deleteTodo = (id) => {
setTodos(todos.filter(todo => todo.id !== id));
};
filter
メソッドで、指定されたID以外のタスクだけを残しています。
タスクの完了・未完了の切り替え
const toggleTodo = (id) => {
setTodos(todos.map(todo =>
todo.id === id
? { ...todo, completed: !todo.completed }
: todo
));
};
map
メソッドで、各タスクを確認しています。
指定されたIDのタスクだけ、完了状態を反転させています。
リストの表示
todos.map(todo => (
<div key={todo.id} className={`todo-item ${todo.completed ? 'completed' : ''}`}>
<input
type="checkbox"
checked={todo.completed}
onChange={() => toggleTodo(todo.id)}
/>
<span className="todo-text">{todo.text}</span>
<button
className="delete-btn"
onClick={() => deleteTodo(todo.id)}
>
削除
</button>
</div>
))
map
メソッドで、各タスクをHTMLに変換しています。
key={todo.id}
は、Reactが効率的に更新するために必要です。
実際に使ってみよう
このToDoリストを実際に使ってみてください。
- テキストボックスにタスクを入力
- 「追加」ボタンをクリック(またはEnterキー)
- チェックボックスで完了・未完了を切り替え
- 「削除」ボタンでタスクを削除
「こんなに本格的なアプリが作れるの?」と思うかもしれませんが、これもCDNで簡単に実現できます。
すごいですよね!
コンポーネントを分割してみよう
ToDoリストが完成したので、次はコンポーネント分割を学びましょう。
なぜコンポーネントを分割するの?
大きなコンポーネントを小さく分割することで、以下のメリットがあります。
- 理解しやすい: 各部分の役割が明確になる
- 再利用できる: 同じコンポーネントを別の場所で使える
- 保守しやすい: 修正するときに影響範囲が限定される
分割されたToDoリスト
同じToDoリストを、複数のコンポーネントに分割してみましょう。
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>React コンポーネント分割</title>
<style>
body {
font-family: Arial, sans-serif;
max-width: 600px;
margin: 0 auto;
padding: 20px;
background-color: #f5f5f5;
}
.todo-app {
background: white;
border-radius: 10px;
padding: 20px;
box-shadow: 0 2px 10px rgba(0,0,0,0.1);
}
.todo-input {
display: flex;
margin-bottom: 20px;
}
.todo-input input {
flex: 1;
padding: 10px;
font-size: 16px;
border: 2px solid #ddd;
border-radius: 5px 0 0 5px;
border-right: none;
}
.todo-input button {
padding: 10px 20px;
font-size: 16px;
background-color: #007bff;
color: white;
border: 2px solid #007bff;
border-radius: 0 5px 5px 0;
cursor: pointer;
}
.todo-item {
display: flex;
align-items: center;
padding: 10px;
border-bottom: 1px solid #eee;
}
.todo-item.completed {
opacity: 0.6;
text-decoration: line-through;
}
.todo-item input[type="checkbox"] {
margin-right: 10px;
}
.todo-text {
flex: 1;
}
.delete-btn {
background-color: #dc3545;
color: white;
border: none;
padding: 5px 10px;
border-radius: 3px;
cursor: pointer;
}
</style>
</head>
<body>
<div id="root"></div>
<script crossorigin src="https://unpkg.com/react@18/umd/react.development.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@18/umd/react-dom.development.js"></script>
<script src="https://unpkg.com/@babel/standalone/babel.min.js"></script>
<script type="text/babel">
// 1. ToDoアイテムコンポーネント
function TodoItem({ todo, onToggle, onDelete }) {
return (
<div className={`todo-item ${todo.completed ? 'completed' : ''}`}>
<input
type="checkbox"
checked={todo.completed}
onChange={() => onToggle(todo.id)}
/>
<span className="todo-text">{todo.text}</span>
<button
className="delete-btn"
onClick={() => onDelete(todo.id)}
>
削除
</button>
</div>
);
}
// 2. ToDoリストコンポーネント
function TodoList({ todos, onToggle, onDelete }) {
if (todos.length === 0) {
return <p>タスクがありません。新しいタスクを追加してください。</p>;
}
return (
<div className="todo-list">
{todos.map(todo => (
<TodoItem
key={todo.id}
todo={todo}
onToggle={onToggle}
onDelete={onDelete}
/>
))}
</div>
);
}
// 3. ToDoインプットコンポーネント
function TodoInput({ value, onChange, onAdd }) {
const handleKeyPress = (e) => {
if (e.key === 'Enter') {
onAdd();
}
};
return (
<div className="todo-input">
<input
type="text"
value={value}
onChange={(e) => onChange(e.target.value)}
onKeyPress={handleKeyPress}
placeholder="新しいタスクを入力..."
/>
<button onClick={onAdd}>追加</button>
</div>
);
}
// 4. 統計表示コンポーネント
function TodoStats({ todos }) {
const completedCount = todos.filter(todo => todo.completed).length;
const totalCount = todos.length;
return (
<div style={{ marginTop: '20px', color: '#666' }}>
<p>完了: {completedCount} / 全体: {totalCount}</p>
{totalCount > 0 && (
<p>進捗: {Math.round((completedCount / totalCount) * 100)}%</p>
)}
</div>
);
}
// 5. メインアプリケーションコンポーネント
function TodoApp() {
const [todos, setTodos] = React.useState([]);
const [inputValue, setInputValue] = React.useState('');
const addTodo = () => {
if (inputValue.trim() !== '') {
const newTodo = {
id: Date.now(),
text: inputValue.trim(),
completed: false
};
setTodos([...todos, newTodo]);
setInputValue('');
}
};
const deleteTodo = (id) => {
setTodos(todos.filter(todo => todo.id !== id));
};
const toggleTodo = (id) => {
setTodos(todos.map(todo =>
todo.id === id
? { ...todo, completed: !todo.completed }
: todo
));
};
return (
<div className="todo-app">
<h1>React ToDoリスト(コンポーネント分割版)</h1>
<TodoInput
value={inputValue}
onChange={setInputValue}
onAdd={addTodo}
/>
<TodoList
todos={todos}
onToggle={toggleTodo}
onDelete={deleteTodo}
/>
<TodoStats todos={todos} />
</div>
);
}
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(<TodoApp />);
</script>
</body>
</html>
機能は同じですが、コードがとても見やすくなりました。
分割されたコンポーネントの解説
各コンポーネントの役割を見てみましょう。
1. TodoItem コンポーネント
function TodoItem({ todo, onToggle, onDelete }) {
return (
<div className={`todo-item ${todo.completed ? 'completed' : ''}`}>
<input
type="checkbox"
checked={todo.completed}
onChange={() => onToggle(todo.id)}
/>
<span className="todo-text">{todo.text}</span>
<button
className="delete-btn"
onClick={() => onDelete(todo.id)}
>
削除
</button>
</div>
);
}
1つのタスクを表示するコンポーネントです。
{ todo, onToggle, onDelete }
で、親から情報を受け取っています。
2. TodoList コンポーネント
function TodoList({ todos, onToggle, onDelete }) {
if (todos.length === 0) {
return <p>タスクがありません。新しいタスクを追加してください。</p>;
}
return (
<div className="todo-list">
{todos.map(todo => (
<TodoItem
key={todo.id}
todo={todo}
onToggle={onToggle}
onDelete={onDelete}
/>
))}
</div>
);
}
タスクの一覧を表示するコンポーネントです。
TodoItem
を複数使って、リストを構成しています。
3. TodoInput コンポーネント
function TodoInput({ value, onChange, onAdd }) {
const handleKeyPress = (e) => {
if (e.key === 'Enter') {
onAdd();
}
};
return (
<div className="todo-input">
<input
type="text"
value={value}
onChange={(e) => onChange(e.target.value)}
onKeyPress={handleKeyPress}
placeholder="新しいタスクを入力..."
/>
<button onClick={onAdd}>追加</button>
</div>
);
}
新しいタスクを入力するコンポーネントです。 Enterキーでもタスクを追加できるようになっています。
4. TodoStats コンポーネント
function TodoStats({ todos }) {
const completedCount = todos.filter(todo => todo.completed).length;
const totalCount = todos.length;
return (
<div style={{ marginTop: '20px', color: '#666' }}>
<p>完了: {completedCount} / 全体: {totalCount}</p>
{totalCount > 0 && (
<p>進捗: {Math.round((completedCount / totalCount) * 100)}%</p>
)}
</div>
);
}
統計情報を表示するコンポーネントです。 完了率の計算も行っています。
5. メインアプリケーション
function TodoApp() {
const [todos, setTodos] = React.useState([]);
const [inputValue, setInputValue] = React.useState('');
// ... 各種関数
return (
<div className="todo-app">
<h1>React ToDoリスト(コンポーネント分割版)</h1>
<TodoInput
value={inputValue}
onChange={setInputValue}
onAdd={addTodo}
/>
<TodoList
todos={todos}
onToggle={toggleTodo}
onDelete={deleteTodo}
/>
<TodoStats todos={todos} />
</div>
);
}
全体をまとめるメインのコンポーネントです。 状態管理と、各コンポーネントの連携を行っています。
コンポーネント分割のメリット
この分割により、以下のメリットが得られます。
- 理解しやすい: 各コンポーネントの役割が明確
- 修正しやすい: 1つのコンポーネントだけを変更できる
- テストしやすい: 個別にテストできる
- 再利用できる: 他のプロジェクトでも使える
「最初は1つのコンポーネントで十分では?」と思うかもしれませんが、アプリが大きくなると分割の重要性がわかってきます。
実際に動かしてみよう
このコンポーネント分割版も、機能は全く同じです。
でも、コードが圧倒的に見やすくなりました。 これがReactの真の力なんです。
すごいですよね!
他のライブラリとの組み合わせ
CDNの素晴らしいところは、他のライブラリと簡単に組み合わせできることです。
Bootstrapと組み合わせてみよう
まず、見た目を美しくするBootstrapと組み合わせてみます。
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>React + Bootstrap</title>
<!-- Bootstrap CDN -->
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet">
</head>
<body>
<div id="root"></div>
<script crossorigin src="https://unpkg.com/react@18/umd/react.development.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@18/umd/react-dom.development.js"></script>
<script src="https://unpkg.com/@babel/standalone/babel.min.js"></script>
<script type="text/babel">
function UserCard({ user }) {
return (
<div className="col-md-4 mb-3">
<div className="card h-100">
<img
src={user.avatar}
className="card-img-top"
alt={user.name}
style={{ height: '200px', objectFit: 'cover' }}
/>
<div className="card-body">
<h5 className="card-title">{user.name}</h5>
<p className="card-text">{user.email}</p>
<p className="card-text">
<small className="text-muted">{user.role}</small>
</p>
</div>
<div className="card-footer">
<button className="btn btn-primary btn-sm me-2">
プロフィール
</button>
<button className="btn btn-outline-secondary btn-sm">
メッセージ
</button>
</div>
</div>
</div>
);
}
function UserList() {
const [users] = React.useState([
{
id: 1,
name: '田中太郎',
email: 'tanaka@example.com',
role: '開発者',
avatar: 'https://via.placeholder.com/300x200/007bff/ffffff?text=田中太郎'
},
{
id: 2,
name: '佐藤花子',
email: 'sato@example.com',
role: 'デザイナー',
avatar: 'https://via.placeholder.com/300x200/28a745/ffffff?text=佐藤花子'
},
{
id: 3,
name: '山田次郎',
email: 'yamada@example.com',
role: 'マネージャー',
avatar: 'https://via.placeholder.com/300x200/dc3545/ffffff?text=山田次郎'
}
]);
return (
<div className="container mt-5">
<div className="row">
<div className="col-12">
<h1 className="text-center mb-4">チームメンバー</h1>
</div>
</div>
<div className="row">
{users.map(user => (
<UserCard key={user.id} user={user} />
))}
</div>
</div>
);
}
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(<UserList />);
</script>
</body>
</html>
このコードを実行すると、プロ級の見た目のカードリストが表示されます。
Bootstrap組み合わせの解説
Bootstrap CDNの読み込み
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet">
BootstrapのCSSをCDNで読み込んでいます。 これだけで、美しいスタイルが使えるようになります。
Bootstrapクラスの使用
<div className="col-md-4 mb-3">
<div className="card h-100">
<img
src={user.avatar}
className="card-img-top"
alt={user.name}
style={{ height: '200px', objectFit: 'cover' }}
/>
<div className="card-body">
<h5 className="card-title">{user.name}</h5>
<p className="card-text">{user.email}</p>
</div>
</div>
</div>
col-md-4
、card
、card-body
などは、すべてBootstrapのクラスです。
これらを使うことで、プロフェッショナルな見た目になります。
Chart.jsと組み合わせてみよう
次は、グラフを表示するChart.jsと組み合わせてみます。
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>React + Chart.js</title>
<style>
body {
font-family: Arial, sans-serif;
max-width: 800px;
margin: 0 auto;
padding: 20px;
}
.chart-container {
margin: 20px 0;
padding: 20px;
border: 1px solid #ddd;
border-radius: 5px;
}
.stats-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
gap: 20px;
margin-bottom: 20px;
}
.stat-card {
padding: 20px;
background-color: #f8f9fa;
border-radius: 5px;
text-align: center;
}
.stat-value {
font-size: 24px;
font-weight: bold;
margin-bottom: 5px;
}
</style>
</head>
<body>
<div id="root"></div>
<!-- Chart.js CDN -->
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
<script crossorigin src="https://unpkg.com/react@18/umd/react.development.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@18/umd/react-dom.development.js"></script>
<script src="https://unpkg.com/@babel/standalone/babel.min.js"></script>
<script type="text/babel">
function SalesChart() {
const chartRef = React.useRef(null);
const chartInstanceRef = React.useRef(null);
React.useEffect(() => {
const ctx = chartRef.current.getContext('2d');
// 既存のチャートがあれば破棄
if (chartInstanceRef.current) {
chartInstanceRef.current.destroy();
}
chartInstanceRef.current = new Chart(ctx, {
type: 'line',
data: {
labels: ['1月', '2月', '3月', '4月', '5月', '6月'],
datasets: [{
label: '売上',
data: [120, 190, 300, 500, 200, 300],
borderColor: 'rgb(75, 192, 192)',
backgroundColor: 'rgba(75, 192, 192, 0.2)',
tension: 0.1
}]
},
options: {
responsive: true,
plugins: {
title: {
display: true,
text: '月別売上推移'
}
},
scales: {
y: {
beginAtZero: true
}
}
}
});
// クリーンアップ関数
return () => {
if (chartInstanceRef.current) {
chartInstanceRef.current.destroy();
}
};
}, []);
return (
<div className="chart-container">
<canvas ref={chartRef}></canvas>
</div>
);
}
function Dashboard() {
const [salesData] = React.useState({
total: 1610,
average: 268,
growth: 15.2
});
return (
<div>
<h1>売上ダッシュボード</h1>
<div className="stats-grid">
<div className="stat-card">
<div className="stat-value" style={{ color: '#007bff' }}>
¥{salesData.total.toLocaleString()}万
</div>
<div>総売上</div>
</div>
<div className="stat-card">
<div className="stat-value" style={{ color: '#28a745' }}>
¥{salesData.average.toLocaleString()}万
</div>
<div>月平均</div>
</div>
<div className="stat-card">
<div className="stat-value" style={{ color: '#fd7e14' }}>
+{salesData.growth}%
</div>
<div>成長率</div>
</div>
</div>
<SalesChart />
</div>
);
}
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(<Dashboard />);
</script>
</body>
</html>
このコードを実行すると、本格的なダッシュボードが表示されます。
Chart.js組み合わせの解説
Chart.js CDNの読み込み
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
Chart.jsのライブラリをCDNで読み込んでいます。
useRefとuseEffectの使用
const chartRef = React.useRef(null);
const chartInstanceRef = React.useRef(null);
React.useEffect(() => {
const ctx = chartRef.current.getContext('2d');
// チャートの作成
chartInstanceRef.current = new Chart(ctx, {
type: 'line',
data: {
labels: ['1月', '2月', '3月', '4月', '5月', '6月'],
datasets: [{
label: '売上',
data: [120, 190, 300, 500, 200, 300],
borderColor: 'rgb(75, 192, 192)',
backgroundColor: 'rgba(75, 192, 192, 0.2)',
tension: 0.1
}]
},
options: {
responsive: true,
plugins: {
title: {
display: true,
text: '月別売上推移'
}
}
}
});
// クリーンアップ関数
return () => {
if (chartInstanceRef.current) {
chartInstanceRef.current.destroy();
}
};
}, []);
useRef
でDOM要素を参照しています。
useEffect
でコンポーネントの初期化時にチャートを作成しています。
クリーンアップ関数で、不要になったチャートを削除しています。
他のライブラリとの組み合わせ
CDNを使えば、以下のようなライブラリも簡単に組み合わせできます。
- Font Awesome: アイコンライブラリ
- Lodash: ユーティリティライブラリ
- Moment.js: 日付操作ライブラリ
- Axios: HTTP通信ライブラリ
「こんなに簡単に組み合わせられるの?」と思うかもしれませんが、CDNなら本当に簡単です。
必要なものを<script>
タグで読み込むだけなんです。
実際の活用場面
React CDNが実際にどのような場面で活用されるかを見てみましょう。
プロトタイプ作成
アイデアを素早く形にしたいときの例を見てみます。
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>レストラン予約システム プロトタイプ</title>
<style>
body {
font-family: Arial, sans-serif;
max-width: 600px;
margin: 0 auto;
padding: 20px;
background-color: #f5f5f5;
}
.form-container {
background: white;
padding: 30px;
border-radius: 10px;
box-shadow: 0 2px 10px rgba(0,0,0,0.1);
}
.form-group {
margin-bottom: 20px;
}
label {
display: block;
margin-bottom: 5px;
font-weight: bold;
color: #333;
}
input, select {
width: 100%;
padding: 10px;
border: 1px solid #ddd;
border-radius: 5px;
font-size: 16px;
}
button {
background-color: #007bff;
color: white;
padding: 12px 30px;
border: none;
border-radius: 5px;
cursor: pointer;
font-size: 16px;
width: 100%;
}
button:hover {
background-color: #0056b3;
}
.success-message {
background-color: #d4edda;
color: #155724;
padding: 15px;
border-radius: 5px;
margin-bottom: 20px;
}
.reservation-summary {
background-color: #f8f9fa;
padding: 20px;
border-radius: 5px;
margin-top: 20px;
}
</style>
</head>
<body>
<div id="root"></div>
<script crossorigin src="https://unpkg.com/react@18/umd/react.development.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@18/umd/react-dom.development.js"></script>
<script src="https://unpkg.com/@babel/standalone/babel.min.js"></script>
<script type="text/babel">
function ReservationForm() {
const [reservation, setReservation] = React.useState({
name: '',
phone: '',
date: '',
time: '',
guests: 2
});
const [submitted, setSubmitted] = React.useState(false);
const handleChange = (field, value) => {
setReservation(prev => ({
...prev,
[field]: value
}));
};
const handleSubmit = (e) => {
e.preventDefault();
setSubmitted(true);
// 実際のシステムでは、ここでAPIにデータを送信
console.log('予約データ:', reservation);
};
if (submitted) {
return (
<div className="form-container">
<div className="success-message">
<h2>予約が完了しました!</h2>
<p>ご予約ありがとうございます。</p>
</div>
<div className="reservation-summary">
<h3>予約内容</h3>
<p><strong>お名前:</strong> {reservation.name}</p>
<p><strong>電話番号:</strong> {reservation.phone}</p>
<p><strong>予約日:</strong> {reservation.date}</p>
<p><strong>時間:</strong> {reservation.time}</p>
<p><strong>人数:</strong> {reservation.guests}名</p>
</div>
<button onClick={() => setSubmitted(false)}>
新しい予約を作成
</button>
</div>
);
}
return (
<div className="form-container">
<h1>レストラン予約システム</h1>
<p>以下のフォームに必要事項を入力してください。</p>
<form onSubmit={handleSubmit}>
<div className="form-group">
<label>お名前</label>
<input
type="text"
value={reservation.name}
onChange={(e) => handleChange('name', e.target.value)}
required
/>
</div>
<div className="form-group">
<label>電話番号</label>
<input
type="tel"
value={reservation.phone}
onChange={(e) => handleChange('phone', e.target.value)}
required
/>
</div>
<div className="form-group">
<label>予約日</label>
<input
type="date"
value={reservation.date}
onChange={(e) => handleChange('date', e.target.value)}
min={new Date().toISOString().split('T')[0]}
required
/>
</div>
<div className="form-group">
<label>時間</label>
<select
value={reservation.time}
onChange={(e) => handleChange('time', e.target.value)}
required
>
<option value="">時間を選択</option>
<option value="17:00">17:00</option>
<option value="17:30">17:30</option>
<option value="18:00">18:00</option>
<option value="18:30">18:30</option>
<option value="19:00">19:00</option>
<option value="19:30">19:30</option>
<option value="20:00">20:00</option>
<option value="20:30">20:30</option>
<option value="21:00">21:00</option>
</select>
</div>
<div className="form-group">
<label>人数</label>
<select
value={reservation.guests}
onChange={(e) => handleChange('guests', parseInt(e.target.value))}
>
{[1,2,3,4,5,6,7,8,9,10].map(num => (
<option key={num} value={num}>{num}名</option>
))}
</select>
</div>
<button type="submit">予約する</button>
</form>
</div>
);
}
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(<ReservationForm />);
</script>
</body>
</html>
このプロトタイプでは、以下の機能を実装しています。
- フォーム入力: 名前、電話番号、日付、時間、人数
- バリデーション: 必須項目のチェック
- 動的な処理: 予約完了後の表示切り替え
- ユーザビリティ: 今日以降の日付のみ選択可能
既存サイトへの部分導入
既存のWebサイトに、一部分だけReactを導入する例です。
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>既存サイト + React部分導入</title>
<style>
body {
font-family: Arial, sans-serif;
margin: 0;
padding: 0;
line-height: 1.6;
}
header {
background-color: #333;
color: white;
padding: 1rem;
text-align: center;
}
.content {
max-width: 800px;
margin: 0 auto;
padding: 20px;
}
.react-widget {
border: 2px solid #007bff;
border-radius: 8px;
padding: 20px;
margin: 20px 0;
background-color: #f8f9fa;
}
.react-widget h3 {
color: #007bff;
margin-top: 0;
}
footer {
background-color: #333;
color: white;
text-align: center;
padding: 1rem;
margin-top: 40px;
}
.traditional-content {
background-color: #ffffff;
padding: 20px;
margin: 20px 0;
border-left: 4px solid #28a745;
}
</style>
</head>
<body>
<!-- 既存のHTMLコンテンツ -->
<header>
<h1>株式会社サンプル</h1>
<p>革新的なWebソリューションを提供</p>
</header>
<div class="content">
<div class="traditional-content">
<h2>会社概要</h2>
<p>私たちは、最新のWeb技術を活用して、お客様のビジネスをサポートしています。</p>
<p>従来のHTMLコンテンツと、最新のReactコンポーネントを組み合わせることで、効率的なWebサイト開発を実現しています。</p>
</div>
<!-- React部分のコンテナ -->
<div class="react-widget">
<div id="contact-form"></div>
</div>
<div class="traditional-content">
<h2>サービス紹介</h2>
<p>以下のサービスを提供しています:</p>
<ul>
<li>Webサイト制作</li>
<li>システム開発</li>
<li>保守・運用</li>
<li>コンサルティング</li>
</ul>
</div>
<!-- もう一つのReact部分 -->
<div class="react-widget">
<div id="newsletter-signup"></div>
</div>
<div class="traditional-content">
<h2>お客様の声</h2>
<p>「迅速で丁寧な対応をしていただき、期待以上の成果を得ることができました。」</p>
<p>「技術力の高さと、分かりやすい説明で、安心してお任せできました。」</p>
</div>
</div>
<footer>
<p>© 2024 株式会社サンプル. All rights reserved.</p>
</footer>
<!-- React CDN -->
<script crossorigin src="https://unpkg.com/react@18/umd/react.development.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@18/umd/react-dom.development.js"></script>
<script src="https://unpkg.com/@babel/standalone/babel.min.js"></script>
<script type="text/babel">
// お問い合わせフォームコンポーネント
function ContactForm() {
const [formData, setFormData] = React.useState({
name: '',
email: '',
subject: '',
message: ''
});
const [submitted, setSubmitted] = React.useState(false);
const handleChange = (field, value) => {
setFormData(prev => ({
...prev,
[field]: value
}));
};
const handleSubmit = (e) => {
e.preventDefault();
setSubmitted(true);
// 実際のシステムでは、ここでAPIにデータを送信
console.log('お問い合わせデータ:', formData);
};
if (submitted) {
return (
<div>
<h3>お問い合わせありがとうございます</h3>
<div style={{
backgroundColor: '#d4edda',
color: '#155724',
padding: '15px',
borderRadius: '5px',
marginBottom: '15px'
}}>
<p>お問い合わせを受け付けました。</p>
<p>内容を確認の上、2営業日以内にご連絡いたします。</p>
</div>
<button
onClick={() => setSubmitted(false)}
style={{
backgroundColor: '#007bff',
color: 'white',
padding: '10px 20px',
border: 'none',
borderRadius: '5px',
cursor: 'pointer'
}}
>
新しいお問い合わせ
</button>
</div>
);
}
return (
<div>
<h3>お問い合わせフォーム</h3>
<form onSubmit={handleSubmit}>
<div style={{ marginBottom: '15px' }}>
<label style={{ display: 'block', marginBottom: '5px', fontWeight: 'bold' }}>
お名前
</label>
<input
type="text"
value={formData.name}
onChange={(e) => handleChange('name', e.target.value)}
style={{ width: '100%', padding: '8px', border: '1px solid #ddd', borderRadius: '4px' }}
required
/>
</div>
<div style={{ marginBottom: '15px' }}>
<label style={{ display: 'block', marginBottom: '5px', fontWeight: 'bold' }}>
メールアドレス
</label>
<input
type="email"
value={formData.email}
onChange={(e) => handleChange('email', e.target.value)}
style={{ width: '100%', padding: '8px', border: '1px solid #ddd', borderRadius: '4px' }}
required
/>
</div>
<div style={{ marginBottom: '15px' }}>
<label style={{ display: 'block', marginBottom: '5px', fontWeight: 'bold' }}>
件名
</label>
<select
value={formData.subject}
onChange={(e) => handleChange('subject', e.target.value)}
style={{ width: '100%', padding: '8px', border: '1px solid #ddd', borderRadius: '4px' }}
required
>
<option value="">件名を選択</option>
<option value="サービスについて">サービスについて</option>
<option value="料金について">料金について</option>
<option value="技術相談">技術相談</option>
<option value="その他">その他</option>
</select>
</div>
<div style={{ marginBottom: '15px' }}>
<label style={{ display: 'block', marginBottom: '5px', fontWeight: 'bold' }}>
お問い合わせ内容
</label>
<textarea
value={formData.message}
onChange={(e) => handleChange('message', e.target.value)}
style={{
width: '100%',
padding: '8px',
border: '1px solid #ddd',
borderRadius: '4px',
minHeight: '100px'
}}
required
/>
</div>
<button
type="submit"
style={{
backgroundColor: '#007bff',
color: 'white',
padding: '10px 20px',
border: 'none',
borderRadius: '5px',
cursor: 'pointer',
fontSize: '16px'
}}
>
送信
</button>
</form>
</div>
);
}
// ニュースレター登録コンポーネント
function NewsletterSignup() {
const [email, setEmail] = React.useState('');
const [subscribed, setSubscribed] = React.useState(false);
const handleSubmit = (e) => {
e.preventDefault();
setSubscribed(true);
// 実際のシステムでは、ここでAPIにデータを送信
console.log('ニュースレター登録:', email);
};
return (
<div>
<h3>ニュースレター登録</h3>
<p>最新の技術情報や、お得な情報をお届けします。</p>
{subscribed ? (
<div style={{
backgroundColor: '#d4edda',
color: '#155724',
padding: '15px',
borderRadius: '5px'
}}>
<p>ニュースレターの登録が完了しました!</p>
<p>ご登録いただいたメールアドレスに確認メールを送信しました。</p>
</div>
) : (
<form onSubmit={handleSubmit}>
<div style={{ display: 'flex', gap: '10px', alignItems: 'center' }}>
<input
type="email"
placeholder="メールアドレスを入力"
value={email}
onChange={(e) => setEmail(e.target.value)}
style={{
flex: 1,
padding: '10px',
border: '1px solid #ddd',
borderRadius: '4px'
}}
required
/>
<button
type="submit"
style={{
backgroundColor: '#28a745',
color: 'white',
padding: '10px 20px',
border: 'none',
borderRadius: '5px',
cursor: 'pointer'
}}
>
登録
</button>
</div>
</form>
)}
</div>
);
}
// 各コンポーネントを対応する要素にレンダリング
const contactRoot = ReactDOM.createRoot(document.getElementById('contact-form'));
contactRoot.render(<ContactForm />);
const newsletterRoot = ReactDOM.createRoot(document.getElementById('newsletter-signup'));
newsletterRoot.render(<NewsletterSignup />);
</script>
</body>
</html>
この例では、以下の点が重要です。
既存コンテンツとの共存
従来のHTMLコンテンツとReactコンポーネントが同じページに共存しています。 段階的な導入が可能なんです。
複数のReactコンポーネント
同じページに複数のReactコンポーネントを配置しています。 それぞれが独立して動作します。
実用的な機能
お問い合わせフォームとニュースレター登録という、実際のWebサイトでよく使われる機能を実装しています。
活用場面のまとめ
React CDNは、以下のような場面で特に有効です。
- 学習・練習: Reactの基本を学ぶ
- プロトタイプ作成: アイデアを素早く形にする
- 既存サイト改善: 部分的にReactを導入する
- デモ・プレゼン: 動的なデモを作成する
- 教育現場: 授業やワークショップで使用する
「こんなに簡単にできるなんて」と思うかもしれませんが、これがCDNの力なんです。
CDNの制限と本格開発への移行
React CDNは素晴らしいですが、いくつかの制限もあります。
CDNの制限事項
CDNを使用する際の主な制限を理解しておきましょう。
パフォーマンス面の制限
- ビルド最適化なし: コードの圧縮・最適化が行われない
- 大規模アプリに不向き: ファイルサイズが大きくなると動作が重くなる
- キャッシュ効率: 自分のコードがキャッシュされない
開発効率の制限
- エラー検出: TypeScriptなどの型チェックが使えない
- コード補完: IDEでの支援機能が限定的
- デバッグ: 開発者ツールでのデバッグが困難
機能面の制限
- モジュール管理: ES6 modulesが使えない
- パッケージ管理: npmの豊富なパッケージが使いにくい
- ビルドツール: WebpackやViteなどのツールが使えない
本格開発への移行タイミング
以下のような場合は、本格的な開発環境への移行を検討しましょう。
移行を検討すべき場面
- アプリが大きくなった: 複数のページや機能が必要
- チーム開発: 複数人での開発が必要
- 本番運用: 実際のサービスとして運用する
- パフォーマンス重視: 高速な動作が求められる
移行の手順
本格的な開発環境への移行は、以下の手順で行います。
# 1. Node.jsプロジェクトの作成
npx create-react-app my-app
# 2. プロジェクトディレクトリに移動
cd my-app
# 3. 開発サーバーの起動
npm start
# 4. 本番ビルド
npm run build
CDNから本格環境への移行例
CDNで作成したコンポーネントを本格的な環境に移行する方法を見てみましょう。
CDN版のコード
<!-- CDN版 -->
<script type="text/babel">
function TodoApp() {
const [todos, setTodos] = React.useState([]);
const [inputValue, setInputValue] = React.useState('');
const addTodo = () => {
if (inputValue.trim() !== '') {
const newTodo = {
id: Date.now(),
text: inputValue.trim(),
completed: false
};
setTodos([...todos, newTodo]);
setInputValue('');
}
};
// ... その他の関数
return (
<div className="todo-app">
<h1>React ToDoリスト</h1>
{/* ... JSX */}
</div>
);
}
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(<TodoApp />);
</script>
本格版のコード
// TodoApp.jsx (本格版)
import React, { useState } from 'react';
import './TodoApp.css';
function TodoApp() {
const [todos, setTodos] = useState([]);
const [inputValue, setInputValue] = useState('');
const addTodo = () => {
if (inputValue.trim() !== '') {
const newTodo = {
id: Date.now(),
text: inputValue.trim(),
completed: false
};
setTodos([...todos, newTodo]);
setInputValue('');
}
};
// ... その他の関数(同じ)
return (
<div className="todo-app">
<h1>React ToDoリスト</h1>
{/* ... JSX(同じ) */}
</div>
);
}
export default TodoApp;
移行のポイント
- import文の追加:
import React from 'react'
- CSS分離: スタイルを別ファイルに移動
- export追加:
export default TodoApp
- ファイル分割: 複数のファイルに分割
移行時の注意点
移行時には、以下の点に注意してください。
開発環境の違い
- エラー表示: より詳細なエラーメッセージ
- ホットリロード: 変更が即座に反映される
- TypeScript: 型チェックが可能
ビルドプロセス
- 最適化: 本番用にコードが最適化される
- バンドル: 複数のファイルが1つにまとめられる
- Tree Shaking: 未使用のコードが削除される
CDNで学んだ知識は、本格的な開発環境でもそのまま活用できます。
「移行は難しそう」と思うかもしれませんが、基本的な概念は同じです。
まとめ
React CDNを使った開発方法について、基本から応用まで詳しく解説しました。
React CDNの主なメリット
あらためて、React CDNの特徴をまとめてみましょう。
- 簡単な開始: HTMLファイル1つですぐに始められる
- 学習に最適: 複雑な設定なしでReactの基本を学習
- プロトタイプ作成: アイデアを素早く形にできる
- 部分導入: 既存サイトに段階的にReactを導入
- 他ライブラリとの組み合わせ: Bootstrap、Chart.jsなどと簡単に連携
効果的な学習の進め方
React CDNでの学習は、以下の順序で進めることをおすすめします。
- 基本のHello World: JSXとコンポーネントの理解
- 状態管理: useStateを使った動的なコンポーネント
- イベント処理: ユーザーとのインタラクション
- リスト表示: 配列データの表示と操作
- コンポーネント分割: 再利用可能な設計
- 外部ライブラリ: 他のCDNライブラリとの組み合わせ
実践的な活用方法
React CDNは、以下のような場面で特に力を発揮します。
- 学習・練習: Reactの基本概念を理解する
- プロトタイプ作成: 新しいアイデアを素早く試す
- 教育現場: 授業やワークショップでの活用
- 既存サイト改善: 部分的なインタラクティブ機能の追加
次のステップ
CDNでReactの基本を理解したら、以下のステップに進むことをおすすめします。
- 本格的な開発環境: create-react-appの使用
- 状態管理ライブラリ: Redux、Zustandなどの学習
- ルーティング: React Routerの活用
- TypeScript: 型安全な開発
- テスト: Jest、React Testing Libraryの使用
最後に
React CDNは、React学習の入り口として非常に優れた選択肢です。 複雑な環境構築に時間を取られることなく、すぐにReactの魅力を体験できます。
「プログラミングは難しそう」と思っていた方でも、HTMLファイル1つから始められるので、きっと楽しく学習できるはずです。
まずは、この記事で紹介したサンプルコードを実際に動かしてみてください。 そして、少しずつ改造してみてください。
慣れてきたら、本格的な開発環境に移行することで、より高度なReactアプリケーションを作れるようになります。
ぜひ、HTMLファイル1つから始めて、Reactの素晴らしい世界を体験してみてください。
あなたのReact学習の成功を、心から応援しています!