はじめに
本記事はReactにこれから一歩を踏み出したいけどチュートリアルの難しい言葉理解してる時間はあまりない、という方に向けて、環境の構築からなんとなく画面が動くまでを解説します。
今回はReact + TypeScriptをベースに説明します。
これを読んでもっと知りたいと思った方は是非公式チュートリアルをお試しください。
https://ja.reactjs.org/tutorial/tutorial.html
目次
環境構築
Node
まずはパッケージ管理ツールであるnpmを利用するためにNodeをインストールします。
インストール
下のリンクからnodeのインストーラをダウンロードし、インストールを行ってください。
https://nodejs.org/ja/
Nodeとnpmのインストール確認
うまくいけばnodeとnpmのバージョンが表示されます。
$ node -v
v16.4.2
$ npm -v
7.18.1
Visual Studio Code
インストール
次に、統合開発環境のVisual Studio Codeをインストールします。
Atomなどでも問題ないですが、個人的に一番便利なのがVisual Studio Codeだと思っています。
https://code.visualstudio.com/download
日本語化
必要に応じて日本語化が可能です。
- Visual Studio Codeを開き、サイドバーから拡張機能のストアに移動します。
- 検索欄に
Japanese
と打ち、Japanese Language Pack
をインストールします。 - Visual Studio Codeを再起動します。
Reactの導入
インストール
今回はcreate react app
という、react公式が提供している環境の一括インストールを利用します。
Visual Studio Codeのターミナルで任意のディレクトリを開き下記のコマンドを実行してください。
$ npx create-react-app {任意のプロジェクト名} --template typescript
Need to install the following packages:
create-react-app
Ok to proceed? (y)
create-react-appをインストールしますか?と聞かれるのでYesと答えます。
確認
このようにいくつかのファイルが生成されていればインストール成功です。
では、実際に動かしてみましょう。
$ npm start
インストールが成功したディレクトリに移動し、上記のコードを入力してください。
ターミナルにこんな文字が表示されれば成功です。
Local: http://localhost:3000
ターミナルの3行目に記載されたこのURLをブラウザで開いてみてください。
このような画面が表示されたと思います。
これで無事Reactの導入完了になります。
Reactの書き方
動かしてみる
まずは試しに今開いているサンプルページを少し触ってみましょう。
{プロジェクト名}/src/App.tsx
を開き、19行目の文字をHello World!
にしてみましょう。
保存するとターミナルに文字が走り、自動的にページが更新されるはずです。
このように、Reactではホットリロードという自動更新機能がデフォルトで導入されています。
.tsxファイル
次に.tsx
というファイルについて簡単に説明します。
先程App.tsx
という名前のファイルを編集しました。見慣れない拡張子だと思いますが、これは「React特有の書き方を利用したファイル」という意味になります。(JavaScriptの場合.jsx
となります)
特徴としては、関数の返り値にHTMLを記載するところが他の記法との大きな違いになります。
Reactの考えとしては「ロジック(JavaScript)とマークアップ(HTML)を別々に書く」従来の技術の分離ではなく、「ロジック(JavaScript)とマークアップ(HTML)を機能ごとにひとまとめにする」という関心の分離を採用しているため、このような記法になります。
コンポーネントとは
Reactについて調べていると、しばしば「コンポーネント」という単語を目にします。
コンポーネントとはロジックとマークアップを両方含む疎結合の部品を指します。
つまり、同じ機能を必要な場所で何度も再利用できるように機能ごとに分離して管理するという考え方です。
ページの余白等を決めるコンポーネント
↓
ページに含まれるコンテンツのコンポーネント
↓
コンテンツに含まれるアイテムコンポーネント
実際に書いてみる
実際に動くコードを作ってみます。
まずは先程見たApp.tsx
の中身をシンプルなものにしてみましょう。
function App() {
return (
<div className="App">
<h1>Hello World!</h1>
</div>
);
}
export default App;
画面を見るとただ「Hello World!」と白い画面に表示されています。
先程話題に出たように、関数の返り値がHTMLになっていることが分かりやすく見えると思います。
変数の利用
このように書き換えてみましょう
function App() {
const text: string = 'Hello World!';
return (
<div className="App">
<h1>{text}</h1>
</div>
);
}
export default App;
画面を見ると何も変化がないことがわかると思います。
上記のように、変数をHTML内に入れられるのも.tsx
の特徴です。
ルーティング
次はボタンを押したら画面が遷移されるようにしたいと思います。
まずは下記のルーティングライブラリをインストールします。
$ npm i react-router-dom
まずApp.tsxを下記のように変更します。
import { Link } from "react-router-dom";
function App() {
const title: string = "Hello World!";
return (
<div className="App">
<h1>{title}</h1>
<Link to='/test'>
ボタン
</Link>
</div>
);
}
export default App;
{プロジェクト名}/src/test.tsx
を作成し下記のコードを記述します。
function Test() {
const title: string = "test";
return (
<div className="Test">
<h1>{title}</h1>
</div>
);
}
export default Test;
その後、{プロジェクト名}/src/index.tsx
を下記のように編集します。
ここでルーティングするURLやコンポーネントを指定しています。
import React from "react";
import ReactDOM from "react-dom";
import "./index.css";
import App from "./App";
import Test from "./Test";
import { BrowserRouter, Route, Routes } from "react-router-dom";
import reportWebVitals from "./reportWebVitals";
ReactDOM.render(
<React.StrictMode>
<BrowserRouter>
<Routes>
<Route path="/" element={<App />} />
<Route path="/test" element={<Test />} />
</Routes>
</BrowserRouter>
</React.StrictMode>,
document.getElementById("root")
);
// If you want to start measuring performance in your app, pass a function
// to log results (for example: reportWebVitals(console.log))
// or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals
reportWebVitals();
画面に戻り、ボタンを押すと画面遷移することがわかると思います。
子コンポーネントとprops
今度はコンポーネント内でコンポーネントを呼び出してみましょう。
コンポーネントの説明で説明したように、コンポーネントは機能を分割したものになります。そのため、例えば画面コンポーネントの中にボタンコンポーネントを呼び出したいという場合は、コンポーネントをコンポーネントの中に呼ぶ、親子関係のような構造が出来上がります。
{プロジェクト名}/src/children/link.tsx
を作成し下記のコードを記述します。
type LinkButtonProps = {
text: string,
link: string
}
function LinkButton(props: LinkButtonProps) {
return (
<div className="LinkButton">
<Link to={props.link}>
{props.text}
</Link>
</div>
);
}
export default LinkButton;
この時、LinkButton.tsx
にtype
というものを宣言しています。
これは型宣言と呼ばれるもので、この型を利用した場合はオブジェクト型でstring型のtext
とstring型のlink
しかこの変数に入りませんという意味になります。TypeScriptはこうやって型を指定していくことで変な値の出入りを防いでいます。
次にApp.tsxを下記のように変更します。
import LinkButton from "./children/LinkButton";
function App() {
const title: string = "Hello World!";
return (
<div className="App">
<h1>{title}</h1>
<LinkButton text="ボタン" link="/test" />
</div>
);
}
export default App;
画面を見るとルーティングの時と同じように動作しているのが分かります。
LinkButton.tsx
は6行目のfunction
の引数に先程作成した型を指定しています。
このコンポーネント関数の引数こそprops
と呼ばれるもので、親コンポーネントから子コンポーネントへ値を受け渡すことが可能になります。
親側で書いた処理を子に渡すことで、子が不要な処理を抱え込まずに済むのがメリットです。
つまり、担当する機能を分割したままにコンポーネントを細かく増やすことができるのです。
React Hooksとstate
まずはこのように「増やす」ボタンを押したらnum
が加算されるように書いてみます。
import LinkButton from "./children/LinkButton";
function App() {
const title: string = "Hello World!";
let num: number = 0;
const increment = () => {
num += 1;
console.log(num);
};
return (
<div className="App">
<h1>{title}</h1>
{num}回押しました。
<LinkButton text="ボタン" link="/test" />
<button type="button" onClick={increment}>増やす</button>
</div>
);
}
export default App;
この書き方では画面の文字が変わらないことが分かります。
Reactでは、値の更新はとある方法で検知させないと画面に反映がされません。
ここで登場するのが状態管理、stateになります。
簡単に説明すると関数の状態を必要な時だけ更新することで、常に最新のHTMLを最低限の処理で返却するという機能です。
いくつか方法がありますが、今回はReact Hooksと呼ばれる機能を利用します。
下記のようにコードを修正してください。
import { useState } from "react";
import LinkButton from "./children/LinkButton";
function App() {
const title: string = "Hello World!";
const [num, setNum] = useState(0);
const increment = () => {
setNum(num + 1);
console.log(num);
};
return (
<div className="App">
<h1>{title}</h1>
{num}回押しました。
<LinkButton text="ボタン" link="/test" />
<button type="button" onClick={increment}>
増やす
</button>
</div>
);
}
export default App;
画面を見ると表示される数字が更新されていることが分かります。
このように、必要な時だけ画面レンダリングを行うことが可能になります。
また、画面右側のconsoleの数字が画面に対して1低いことが気になった方もいるかと思います。
これはstateの更新は一瞬で済むものではなく、多少時間がかかってしまうため即時に変更後の値を取り出すのは難しいことを表しています。
この値が更新されたことを検知する方法もあるのですが、さらに多くのHooksを理解する必要があるため今回は省略します。
state管理に関するHooksについて紹介した記事があるのでそちらも参照していただけると理解が深まるかと思います。
https://qiita.com/r-terao/items/10d6fe6047f1d117b59a
おわりに
今回はReact + TypeScriptの環境構築から、ある程度コーディングすることが可能なレベルまでのチュートリアルをなるべく単語数少なめで紹介させていただきました。
Reactの良いところは、やはり関心事の分離という考え方にあると思います。
これを利用することで、例えば複数画面で再利用されるボタンコンポーネントを先に作ってから大人数で同時に利用して作業しても、処理部分を持っているのは呼び出す側のコンポーネントのためコンフリクトを起こしにくいのです。
このように大量にコンポーネントを生み出すような規模の大きい開発で大いに役立つReactというフレームワークを皆様一度利用してはいかがでしょうか?