令和のReactに再挑戦
はじめに
過去記事でVueについての記事をいくつか書いておりますが、実はSPAの勉強をし始めた当初、Reactに挑戦しなかなかわからなかったためVueで学習を進めたという経緯があります。
今回は令和になったということで、Reactに再挑戦してみようというものです。
以下の方向けに書いていきたいと思っております。
- Reactの初学者
- javascriptは書いたことがある
- webアプリを作りたい
そもそもReactとは
Reactの公式サイトをみると以下のように言葉が添えられています。
「ユーザインターフェース構築のための JavaScript ライブラリ」
ブラウザ上に表示する全体をコンポーネントという単位に分解し、そのコンポーネントを実装するのに非常に楽な開発体系を提供するライブラリと考えております。よりUIライクな発想で開発を進めるためのライブラリとも取れるかと思います。
React を起動する
Reactを起動するにはPCにnpmもしくはyarnのコマンドを叩ける状態にしてもらいたいと思います
今回はyarnを利用させていただきます。
以下のコマンドでreact-testという名前のディレクトリが作成されます。こちらのディレクトリに一式のファイルが揃っています。
yarn create react-app react-test
このコマンドを打つと色々とファイルが作成されます。一旦動作させてみましょう。devサーバを立ち上げてみます。
yarn run start
そうするとこんな画面が立ち上がるかと思います。これでreactで動作するプログラムをブラウザで確認できたことになります。ここをスタートとします。
よりシンプルなファイルの構成に
今回はreactを挫折せずに学ぶため、ここで作成されたファイルの大半を削除し、よりシンプルに動作させたいと思います。
なお、package.jsonやyarn.lock, node_modulesについては通常のnodeを用いた開発とあまり差がないため、省略したいと思います。ここでのターゲットはsrcやpublic内にあるファイルです。とりあえず最小のコンポーネントを作るため、他のファイルとスタイルシートを削除し、コンポーネント用のディレクトリを作成します。
cd src
rm App.css App.test.js index.css logo.svg reportWebVitals.js setupTests.js
mkdir components
今回作りたいのは
components -> index.js
だけでことが足ります。
ここで今回はjsではなくjsxの形式でコードを書いていくため、拡張子を変更します。ベースはApp.jsとし、最終的にApp.jsを削除します。
cp App.js components/Greeting.jsx
cp App.js components/Introduce.jsx
cp App.js components/Coin.jsx
rm App.js
ここまでで以下のディレクトリ構成になるかと思います。
pwd
/react-test/src
tree .
.
├── components
│ ├── Coin.jsx
│ ├── Greeting.jsx
│ └── Introduce.jsx
└── index.js
1 directory, 4 files
今回やりたいのは components以下に上記の3つのコンポーネントを作成し、index.jsでそれらのファイルを読みこんでhtmlファイルにレンダリングするというものです。
JSXの解説
非常にシンプルですが、javascriptの中にhtmlの形式を書くことができるようにするものです。
React公式のJSXの解説
この中から以下を抜粋。
const element = <h1>Hello, world!</h1>;
これは JSX と呼ばれる JavaScript の構文の拡張です。
UI がどのような見た目かを記述するために、React とともに JSX を使用することを私たちはお勧めしています。
JSX はテンプレート言語を連想させるでしょうが、JavaScript の機能を全て備えたものです。
JSX は React “要素” を生成します。
次の章で React 要素を DOM に変換する方法について見ていきます。
以下では、JSX を使い始めるのに必要な基礎を学ぶことができます。
jsの変数にhtmlの値を代入するような書き方ですが、このような書き方を許してくれるのがjsxの特徴です。
Greetingコンポーネントの作成
index.jsを以下のように書き換えます。
import React from 'react';
import ReactDOM from 'react-dom/client';
import { Greeting } from './components/Greeting.jsx';
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
<React.StrictMode>
<Greeting />
</React.StrictMode>
);
コンポーネントを作っていきます。
import React from 'react';
export const Greeting = () => {
const greet = 'Hello, world';
return(
<h1>{ greet }</h1>
);
}
これで
http://localhost:3000
にアクセスし、以下のようになっていたら成功です。
Greetingというコンポーネントを作成し、それをindex.jsを経由してhtmlにレンダリングしています。(実際にindex.jsのコードを読むと、rootのidを一度取得し、その部分にレンダリングしています)
Greeting.jsxのコードについて解説
私が昔reactに手を出したときにはクラスの形式で書いていた気がするのですが、今はこの関数コンポーネントという書き方もあるようです。こちらで書いていきたいと思います。拡張子はjsxとしてください。
関数として書くことで、vueなどの書き方とも比較し直感的でシンプルなコードに感じます。今回のコードではアロー型の関数を使っています。ベースはjavascriptのため、constなどの変数宣言を使用して、返り値にはjsxの特権を活かしてhtmlを返しています。
Introduceコンポーネントの作成
基本的なreactを用いたコンポーネントの作成はGreetingコンポーネントでOKとして、次は値の受け渡しを行うpropsを試します。これはVueでもある仕組みで、簡単にいうと呼び出し親から子コンポーネントに値を受け渡し、その値を表示に反映するというものです。
index.jsを編集します。Introduce.jsxを読み込むようにしました。
import React from 'react';
import ReactDOM from 'react-dom/client';
import { Greeting } from './components/Greeting.jsx';
import { Introduce } from './components/Introduce.jsx';
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
<React.StrictMode>
<Introduce name="qiita" age="20" />
<Greeting />
</React.StrictMode>
);
Introduce.jsxを編集していきます。
import React from 'react';
export const Introduce = props => {
return(
<h1>I am {props.name}, {props.age} years old </h1>
);
}
こちらでブラウザで再度表示すると以下のようになります。
親コンポーネントからPropsの記述により、値を取得していることがわかります。
//---------------------------------------------------------------------//
//渡す側 index.js (親コンポーネント内)
<Introduce name="qiita" age="20" />
//---------------------------------------------------------------------//
//受け取る側 Introduce.jsx (子コンポーネント内)
export const Introduce = props => {
return(
<h1>I am {props.name}, {props.age} years old </h1>
);
}
//---------------------------------------------------------------------//
Coinコンポーネントの作成
次はReact Hooksを試します。非常にわかりやすいサイトがありましたので、このサイトをベースに解説します。
非常にわかりやすいサイト
まずはコンポーネントから。上のサイトのテストコードをさらにシンプルにします。Stateを関数から扱うためにHooksを利用します。
import React, { useState } from 'react';
export const Coin = () => {
// isVisible:stateを宣言する。
// setVisibility:stateを更新する関数を宣言する。
// useStateの引数はisVisibleの初期値を指定する。
const [isVisible, setVisibility] = useState(true);
// isVisibleを反転する関数を定義する。
const updateVisibility = () => {
setVisibility(!isVisible);
};
return(
<React.Fragment>
<button onClick={updateVisibility}>
反転ボタン
</button>
<div>
{isVisible
?
<div>
<p>オモテです</p>
</div>
:
<div>
<p>ウラです</p>
</div>
}
</div>
</React.Fragment>
);
}
コンポーネントでは以下の処理をしています。
- stateを宣言する。
- stateを更新する関数を宣言する。
- useStateの引数はisVisibleの初期値を指定する。
- stateを更新する関数をラップする関数を作成する。
- 実際に呼び出す(今回はボタンアクションonClickに対して上のラッパー関数を呼び出しています)
また、returnで複数要素を返却する際にで覆っています。
フラグメント
コインのオモテとウラを変更した際に、その判定を行い、表示を変えることをしていますが、これはif文によって実施しています。
{isVisible
?
<div>
<p>オモテです</p>
</div>
:
<div>
<p>ウラです</p>
</div>
}
コンポーネントの作成は終わりましたので、index.jsでもCoin.jsxを読み込むように編集します。
import React from 'react';
import ReactDOM from 'react-dom/client';
import { Greeting } from './components/Greeting.jsx';
import { Introduce } from './components/Introduce.jsx';
import { Coin } from './components/Coin.jsx';
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
<React.StrictMode>
<Introduce name="taro" age="10" />
<Greeting />
<Coin />
</React.StrictMode>
);
ここまでコードを書いてきてブラウザ確認すると、以下のように表示されるかと思います。反転ボタンを押すとオモテとウラが反転します。
おわりに
今回は非常に単純なreactのアプリケーションを作成しました。シンプルなファイル構成にしたことでreactの本質部分を挫折なく学んでいくことができると思います。
引き続き次回以降の記事で以下を進めていくことを考えております。
- Hooksの他の関数
- Contextの利用
- プロジェクトのTypeScript化/CSS
- Reduxの利用