今回やること
前回は、このシリーズで作る 「気になるものリスト」の全体像を確認しました。
今回はいよいよReactを動かします。
Reactのプロジェクトを作成して、ブラウザに「気になるものリスト」という文字を表示するところまで進めてみましょう。
公開日:更新日:
前回は、このシリーズで作る 「気になるものリスト」の全体像を確認しました。
今回はいよいよReactを動かします。
Reactのプロジェクトを作成して、ブラウザに「気になるものリスト」という文字を表示するところまで進めてみましょう。
このシリーズでは、Reactを使って 本・漫画・映画・アニメ・ゲーム・音楽・家具などの「気になるもの」を管理するアプリ を作っていきます。
名前・カテゴリ・ステータス・価格・メモを登録し、最終的には一覧・新規登録・編集の3画面で、編集・削除・検索・絞り込みなどができるアプリを目指します。
前回は、まだアプリの設計を確認しただけでした。
今回はReactの開発環境を用意して、 ブラウザに最初の画面を表示できる状態にします。
まだ気になるものを登録したり、一覧表示したりはできません。まずはアプリを動かすためのスタート地点を作りましょう。
今回は、Reactの開発環境を作るためにViteを使います。
Viteは、Reactなどを使ったフロントエンド開発を始めるための開発ツールです。必要なファイルをまとめて用意してくれるので、Reactの学習をすぐに始められます。
また、Viteを使うにはNode.jsが必要です。Node.jsがまだインストールされていない場合は、先に準備しておきましょう。
ターミナルを開いて、次のコマンドを実行します。
このコマンドを実行すると、いくつかの確認が表示されます。順番に進めていきましょう。
今回は、プロジェクト名をkininaru-listとしています。
npm create vite@latest kininaru-list
初回実行時などは、次のような確認が表示されることがあります。
これは、Viteのプロジェクトを作成するためのcreate-viteをインストールしてよいか確認しています。
yを入力してEnterキーを押します。
※表示されるcreate-viteのバージョンは、実行する時期によって異なる場合があります。
Need to install the following packages:
create-vite@9.1.2
Ok to proceed? (y)
次に、使用するフレームワークを選択します。
Reactを選択してEnterキーを押します。
Select a framework:
React
続いて、使用する言語や構成を選択します。
JavaScriptを選択してEnterキーを押します。
Select a variant:
JavaScript
環境によっては、使用するLinter(リンター)を選択する確認も表示されます。
Linterは、コードに問題がないかチェックするためのツールです。
このシリーズでは、ESLintを選択してEnterキーを押します。
Which linter to use?
Oxlint
ESLint
続いて、次の確認が表示されます。
これは、必要なパッケージのインストールと開発用サーバーの起動を、このまま続けて行うか確認しています。
このシリーズでは手順を1つずつ確認するため、Noを選択してEnterキーを押します。
Install with npm and start now?
Yes
No
確認が完了すると、Reactを使うために必要なファイルが入った
kininaru-list
フォルダが作成されます。
次に、作成したフォルダへ移動します。
cd kininaru-list
続いて、必要なパッケージをインストールします。
npm install
これでReactアプリを動かす準備ができました。
作成したkininaru-listフォルダ内で、次のコマンドを実行して、開発用のサーバーを起動します。
npm run dev
ターミナルにURLが表示されるので、ブラウザで開いてみましょう。
Viteでは、通常は
http://localhost:5173/
が表示されます。
ただし、5173番ポートがすでに使用されている場合は、
5174番など別のポート番号が使われることがあります。
ターミナルに表示されたURLを、 Ctrlキーを押しながらクリックするとブラウザで開けます。 クリックできない場合は、URLをコピーしてブラウザのアドレスバーに貼り付けてください。
Viteが用意した最初のReact画面が表示されれば、プロジェクトの作成は成功です。
Viteでプロジェクトを作成すると、いくつかのファイルとフォルダが用意されます。Viteのバージョンによって生成されるファイルは多少異なることがありますが、まずは次の項目だけ確認すれば十分です。
src:Reactのソースコードを置くフォルダsrc/App.jsx:このシリーズで主に画面を作っていくファイルsrc/main.jsx:Reactアプリを起動する入口src/index.css:このシリーズでアプリの見た目を整えるために使用するCSSその他のファイルは、必要になったときに確認すれば大丈夫です。
プロジェクトは動きましたが、今表示されているのはViteが用意したサンプル画面です。
ここから少しずつ「気になるものリスト」の画面に変えていきます。まずはh1だけを表示します。
src/App.jsx
を開いて、もともと書かれている内容をすべて削除し、次のコードに書き換えてください。
export default function App() {
return <h1>気になるものリスト</h1>;
}
ファイルを保存して、ブラウザを確認してみましょう。
開発用サーバーを起動している間は、コードを保存すると変更内容がブラウザに自動的に反映されます。
反映されない場合は、ブラウザを再読み込みして確認してみましょう。
次のように「気になるものリスト」と表示されればOKです。
また、ReactではAppのように画面を作るためのまとまりをコンポーネントと呼びます。コンポーネントについては、後の記事で詳しく見ていきます。
先ほどのコードを見て、「JavaScriptのファイルなのに、HTMLが書いてある?」と思ったかもしれません。
Reactでは、このHTMLによく似た書き方をJSXと呼びます。
JSXを使うと、画面に表示したい内容をHTMLに近い感覚で書くことができます。
見た目はHTMLとよく似ていますが、まったく同じではありません。
たとえば、HTMLでは
class
と書くところを、JSXでは
className
と書きます。
<div className="item-card">
気になるもの
</div>
次に、説明文のp要素を追加しましょう。
ただし、このまま保存するとブラウザにエラーが表示されます。
export default function App() {
return (
<h1>気になるものリスト</h1>
<p>気になるものを管理するアプリです。</p>
);
}
Reactでは複数のJSX要素を返す場合は、1つのまとまりにまとめる必要があります。
まずはdivで囲んで解決してみましょう。
export default function App() {
return (
<div>
<h1>気になるものリスト</h1>
<p>気になるものを管理するアプリです。</p>
</div>
);
}
保存してブラウザに2つの要素が表示されればOKです。
開発者ツールのElementsを開くと、divが実際のHTML要素として存在していることを確認できます。
divは便利ですが、単に要素をまとめるためだけに余分なHTML要素を追加したくない場合もあります。
その場合は、ReactのFragmentを使います。
Fragmentを使うと、余分なHTML要素を追加せずに複数の要素をまとめられます。
Fragmentは<Fragment>...</Fragment>と書きますが、
<>...</>という短縮記法も使えます。
今回は短縮記法を使ってみましょう。
export default function App() {
return (
<>
<h1>気になるものリスト</h1>
<p>気になるものを管理するアプリです。</p>
</>
);
}
見た目はdiv版と同じですが、Elementsを確認すると、Fragmentに対応するHTML要素は追加されていません。
Fragmentは複数のJSX要素をまとめながら、divのような余分なHTML要素を追加しない仕組みです。
このシリーズでは、ReactとJavaScriptの学習に集中するため、今後の記事で使うアプリ全体のCSSを今回まとめて用意しておきます。
CSSは、次のコードをそのままsrc/index.cssへコピーして使ってください。
※今回は、CSSの細かい内容まで理解しなくても大丈夫です。
Viteの初期状態ではsrc/App.cssもありますが、このシリーズでは使用しません。CSSはsrc/index.cssにまとめるため、src/App.cssは削除してください。
後の記事で、ここで用意したCSSを使いながら画面の見た目を整えていきます。
* { box-sizing: border-box; }
body {
margin: 0;
color: #334155;
background: #f4fbfc;
font-family: system-ui, -apple-system, "Segoe UI", sans-serif;
line-height: 1.5;
}
#root {
max-width: 1100px;
margin: 0 auto;
padding: 32px 20px;
}
.list-screen,
.form-screen {
border: 1px solid #d8eef2;
border-radius: 10px;
background: #fff;
box-shadow: 0 2px 8px rgb(15 118 110 / 8%);
padding: 32px 20px;
}
.form-screen {
max-width: 680px;
margin: 0 auto;
}
h1,
h2 {
margin: 0 0 20px;
color: #155e75;
}
h1 {
font-size: 2rem;
letter-spacing: .02em;
}
h1::before {
content: "✦";
margin-right: 8px;
color: #14b8a6;
}
h2 { font-size: 1.4rem; }
p { margin: 0 0 16px; }
.list-header,
.screen-header,
.form-actions {
display: flex;
align-items: center;
gap: 16px;
}
.list-header,
.screen-header { justify-content: space-between; }
.header-actions {
display: flex;
align-items: center;
gap: 12px;
margin-left: auto;
}
.list-header { margin-bottom: 20px; }
.screen-header { max-width: 640px; }
.list-header,
.screen-header { padding-bottom: 12px; border-bottom: 2px solid #dff7fa; }
.form-actions { justify-content: flex-end; }
.screen-title {
max-width: 640px;
margin-top: 24px;
padding-left: 10px;
border-left: 3px solid #14b8a6;
font-size: 1.5rem;
font-weight: 700;
}
.edit-title { border-left-color: #0e7490; }
.screen-header h1 { margin-bottom: 0; }
.filters {
display: flex;
flex-wrap: wrap;
align-items: end;
gap: 12px;
margin-bottom: 16px;
padding: 12px;
border: 1px solid #d8eef2;
border-radius: 6px;
background: #f8fdfe;
}
label {
display: flex;
flex-direction: column;
gap: 4px;
font-size: .95rem;
}
input,
select,
textarea {
min-width: 0;
padding: 8px 10px;
border: 1px solid #b8c2cc;
border-radius: 4px;
color: inherit;
background: #fff;
font: inherit;
}
input:focus,
select:focus,
textarea:focus {
outline: 2px solid #a5f3fc;
border-color: #0891b2;
}
input,
select { height: 42px; }
input[type="search"] { min-width: 240px; }
textarea { min-height: 100px; resize: vertical; }
form {
display: flex;
flex-direction: column;
gap: 14px;
max-width: 640px;
margin-bottom: 16px;
}
.form-actions {
display: flex;
align-items: center;
gap: 12px;
margin-top: 2px;
}
button {
margin: 4px 8px 4px 0;
padding: 8px 14px;
border: 1px solid #0e7490;
border-radius: 4px;
color: #fff;
background: #0e7490;
font: inherit;
cursor: pointer;
}
button.danger {
border-color: #b42318;
background: #b42318;
}
button.secondary {
border-color: #94a3b8;
color: #334155;
background: #fff;
}
table {
width: 100%;
min-width: 700px;
margin-top: 20px;
border-collapse: collapse;
}
th,
td {
padding: 10px;
border: 1px solid #cbd5e1;
text-align: left;
vertical-align: top;
}
th {
color: #155e75;
background: #ecfeff;
}
tbody tr:hover { background: #f8fdfe; }
CSSをコピーして保存すると、次のように画面の見た目が変わります。
Reactのコードには、Reactの仕組みとJavaScriptの機能が一緒に登場します。
今回登場したものを整理すると、次のようになります。
| 種類 | 今回登場したもの |
|---|---|
| React | JSXを使った画面表示、Fragment |
| JavaScript | function |
今後も「これはReactの機能なのか、それともJavaScriptなのか」をできるだけ分けながら進めていきます。
今回の作業ができているか、次のポイントを確認してみましょう。
npm run devでアプリを起動できたApp.jsxを書き換えるとブラウザの表示も変わったここまでできていれば、第2回は完了です。
今回はまだ文字を表示しただけですが、これで「気になるものリスト」を育てていくための土台ができました。
次回は、画面名をStateで管理して、 一覧画面と新規登録画面を切り替えてみましょう。