環境構築・JSXの書き方・データの移行
このパートで学ぶこと
- Vite で React プロジェクトを作る
- JSX で HTML を書く
useStateで状態を管理する- データファイルを React で使えるようにする
ステップ1|Vite で React プロジェクトを作ろう
Vite とは?
React のプロジェクトを素早く作れるツールです。
今まで index.html を直接ブラウザで開いていましたが、
React では 開発サーバーを起動してブラウザで確認 します。
プロジェクトを作成しよう
ターミナルを開き、作業したいフォルダに移動してから以下を実行します。
npm create vite@latest touring-react -- --template react
📌
touring-reactがプロジェクト名です。好きな名前に変えても OK です。
次に、作成されたフォルダに移動して必要なパッケージをインストールします。
cd touring-react
npm install
インストールが終わったら、開発サーバーを起動します。
npm run dev
ブラウザで http://localhost:5173 を開くと、Vite のサンプルページが表示されます。
生成されたファイルを確認しよう
touring-react/
├── src/
│ ├── App.jsx ← メインのコンポーネント(ここを中心に編集する)
│ ├── App.css ← App.jsx 用のCSS
│ ├── main.jsx ← React の起動ファイル(基本触らない)
│ └── index.css ← グローバルなCSS
├── index.html ← エントリーポイント(基本触らない)
└── package.json ← プロジェクトの設定ファイル
やってみよう
-
npm run devでブラウザにサンプルページが表示されることを確認しましょう -
src/App.jsxを開いて、return(...)の中身を全部消して<h1>ツーリングスポットナビ</h1>だけにしてみましょう - 保存すると、ブラウザが自動で更新されることを確認しましょう(これが Hot Reload です)
ステップ2|不要なファイルを整理しよう
最初から入っているサンプルを消そう
Vite で作ると最初からサンプルコードが入っています。
使わないファイルを消して、スッキリした状態から始めましょう。
削除するファイル
-
src/App.css(Vite のサンプル用CSS) -
src/assets/フォルダごと
src/index.css の中身を全部消す
(あとでツーリングサイトの style.css の内容をここに貼ります)
src/App.jsx をこの状態にする
function App() {
return (
<div>
<h1>ツーリングスポットナビ</h1>
</div>
);
}
export default App;
src/main.jsx を確認する(変更不要)
import { StrictMode } from 'react'
import { createRoot } from 'react-dom/client'
import './index.css'
import App from './App.jsx'
createRoot(document.getElementById('root')).render(
<StrictMode>
<App />
</StrictMode>,
)
📌
main.jsxは「Appコンポーネントをindex.htmlの#rootに表示する」という起動ファイルです。
Vanilla JS でのdocument.getElementById('root')と同じ役割です。
やってみよう
- 不要なファイルを削除して、ブラウザに「ツーリングスポットナビ」と表示されることを確認しましょう
-
index.cssに今のstyle.cssの内容をコピーして、スタイルが当たることを確認しましょう
ステップ3|JSX で HTML を書こう
JSX とは?
React では、JavaScript の中に HTML のような書き方ができます。これを JSX といいます。
// これが JSX
function App() {
return (
<div className="main">
<h1>タイトル</h1>
<p>テキスト</p>
</div>
);
}
HTML と JSX の違いを知ろう
見た目はほぼ同じですが、いくつか違うルールがあります。
① class は className と書く
// HTML
<div class="container">
// JSX
<div className="container">
📌
classは JavaScript の予約語(クラス構文)なので、JSX ではclassNameと書きます。
② 全てのタグは閉じる
// HTML(閉じなくてもよい)
<input type="text">
<br>
// JSX(必ず閉じる)
<input type="text" />
<br />
③ return できるのは1つの要素だけ
// NG:2つの要素を並べて返せない
return (
<h1>タイトル</h1>
<p>テキスト</p>
);
// OK:1つの要素で包む
return (
<div>
<h1>タイトル</h1>
<p>テキスト</p>
</div>
);
// OK:<> </> で包む(余分なdivを作りたくない場合)
return (
<>
<h1>タイトル</h1>
<p>テキスト</p>
</>
);
④ JavaScript の値は {} で埋め込む
const name = '吾妻磐梯スカイライン';
return (
<p>{name}</p> // → <p>吾妻磐梯スカイライン</p>
);
やってみよう
- 今の
index.htmlの<header>部分を JSX に変換してApp.jsxに書いてみましょう -
class→classNameに変え忘れがないか確認しましょう
ステップ4|データファイルを React で使えるようにしよう
import / export とは?
Vanilla JS では <script src="./spots.js"> で読み込んでいましたが、
React(Vite)では import / export を使ってファイルを読み込みます。
参考:export の書き方
// src/data/spots.js
export const spots = [
{
name: '吾妻磐梯スカイライン',
lat: 37.71361,
// ...
}
];
参考:import の書き方
// App.jsx の一番上に書く
import { spots } from './data/spots';
📌
export constで書いたものは{ }で受け取ります(名前付きエクスポート)。
コンポーネントはexport defaultで書くので{ }なしで受け取ります。
ファイルを作ろう
src/data/ フォルダを作り、その中に spots.js を作ります。
src/
├── data/
│ └── spots.js ← 今の spots.js の内容をここに移す
├── App.jsx
└── ...
やってみよう
-
src/data/spots.jsを作り、元のspots.jsから配列をコピーしてexport const spots = [...]に書き換えましょう -
App.jsxでimport { spots } from './data/spots'と書きましょう -
console.log(spots)をApp.jsxに書いて、ブラウザの開発者ツールにデータが出ることを確認しましょう
ステップ5|useState で状態を管理しよう
useState が必要な理由
React では、ただの変数を変えても画面は更新されません。
// NG:これでは画面が変わらない
let count = 0;
function App() {
return (
<button onClick={() => { count++; }}>
{count}
</button>
);
}
画面に反映させたい値は useState で管理する必要があります。
useState の書き方
import { useState } from 'react';
function App() {
const [count, setCount] = useState(0); // 初期値は 0
return (
<button onClick={() => setCount(count + 1)}>
{count} 回クリック
</button>
);
}
-
count:現在の値(読み取り専用) -
setCount(新しい値):値を変えて画面を更新する関数 -
useState(0):0が初期値
📌
setCount(count + 1)を呼ぶと、React が画面を自動で再描画します。
値を変えるときは必ずset〇〇関数を使う ことがルールです。
絞り込み条件を useState で管理しよう
絞り込みで使う「選択中のエリア」「選択中のタイプ」などを useState で管理します。
参考:複数の状態を持つ書き方
const [selectedArea, setSelectedArea] = useState(''); // 初期値は空文字
const [selectedTypes, setSelectedTypes] = useState([]); // 複数選択なので配列
const [selectedSeasons, setSelectedSeasons] = useState([]);
const [selectedLevels, setSelectedLevels] = useState([]);
参考:セレクトボックスの値を useState と連動させる
<select
value={selectedArea}
onChange={e => setSelectedArea(e.target.value)}
>
<option value="">選択してください</option>
<option value="hokkaido">北海道</option>
{/* ... */}
</select>
📌
value={selectedArea}で「今の状態を表示」、
onChangeで「変えたとき状態を更新」する、この組み合わせが React のフォームの基本です。
参考:ボタンのトグル(active クラスの切り替え)
// 配列に含まれていれば active、なければ非 active
<button
className={selectedTypes.includes('海') ? 'select-button active' : 'select-button'}
onClick={() => {
if (selectedTypes.includes('海')) {
setSelectedTypes(selectedTypes.filter(t => t !== '海'));
} else {
setSelectedTypes([...selectedTypes, '海']);
}
}}
>
海
</button>
やってみよう
-
selectedArea、selectedTypes、selectedSeasons、selectedLevelsの4つをuseStateで宣言しましょう - セレクトボックスに
valueとonChangeを設定して、選択した値が変わることをconsole.logで確認しましょう - ボタンを押したとき
selectedTypesに値が追加・削除されることを確認しましょう
ステップ6|絞り込みロジックを移そう
filterSpots 関数はそのまま使える
今の script.js にある filterSpots 関数は純粋な JavaScript なので、ほぼそのまま使えます。
src/utils/filterSpots.js というファイルに切り出して、export しましょう。
参考:ユーティリティ関数の切り出し
// src/utils/filterSpots.js
export function filterSpots(spots, area, types, seasons, levels) {
return spots.filter(spot => {
if (area && spot.area !== area) return false;
if (types.length > 0 &&
!(Array.isArray(spot.type)
? spot.type.some(t => types.includes(t))
: types.includes(spot.type))) return false;
// seasons、levels も同様に書く
return true;
});
}
絞り込み結果も useState で持とう
絞り込んだあとのスポット一覧を useState で管理します。
初期値は「全件」にしておきます。
参考:絞り込み結果の状態
const [filteredSpots, setFilteredSpots] = useState(spots);
参考:検索ボタンを押したとき
<button onClick={() => {
const result = filterSpots(spots, selectedArea, selectedTypes, selectedSeasons, selectedLevels);
setFilteredSpots(result);
}}>
検索する
</button>
参考:リセットボタンを押したとき
<button onClick={() => {
setSelectedArea('');
setSelectedTypes([]);
setSelectedSeasons([]);
setSelectedLevels([]);
setFilteredSpots(spots); // 全件に戻す
}}>
リセット
</button>
やってみよう
-
src/utils/filterSpots.jsを作り、元の関数を移しましょう -
filteredSpotsの状態を作り、検索ボタンで絞り込み結果が変わることをconsole.logで確認しましょう - リセットボタンで全件に戻ることを確認しましょう
Part 1 まとめ
このパートで作ったものを整理します。
src/
├── data/
│ └── spots.js ← スポットデータ(export あり)
├── utils/
│ └── filterSpots.js ← 絞り込み関数(export あり)
├── App.jsx ← useState でエリア・タイプ・季節・難易度・絞り込み結果を管理
├── main.jsx
└── index.css ← style.css の内容をコピー
学んだこと
- Vite で React プロジェクトを作る方法
- JSX の書き方(
className、閉じタグ、{}) -
import/exportでファイルをつなぐ方法 -
useStateで状態を管理して画面を更新する方法
→ Part 2 では、コンポーネント分割・Google マップ表示に進みます