社内でReactの勉強会をした時に作成した、Reactの基本となる用語や考え方をついて紹介します。Reactに興味がある方に、少しでも多くの人にReactについて慣れ親しんでもらえると嬉しいです。
前提事項
- React 16.8から導入されたhooksを利用した記法に則って記載しております
- JavaScript(ES6)の構文をベースに記載をしております
アロー関数
ES6から使えるようになった記法です。下記のように関数を宣言することができます
// 通常の記法
fuction hogehoge() {
}
// アロー関数を使った関数宣言
const hogehoge = () => {
}
import
他のモジュールをimportすることができます。reactでは一般的にnpm経由でインストールしたファイルを読み込んで利用します。
import React from 'react';
import ReactDOM from 'react-dom';
Reactとは?
Reactとは、ユーザインターフェイスを作るためのJavaScriptのライブラリです。(よく間違われますが、フレームワークではないそうです。)
UIをコンポーネント(部品)と呼ばれる単位で作成するのが特徴で、この組み合わせで複雑なUIを柔軟に構成することができます。React要素と呼ばれる仮想DOMを生成、これをもとにレンダリングをします。
ReactでHello World!
下記のように書くことができます。
HTMLファイル
<div id="root"></div>
JSファイル
import React from 'react';
import ReactDOM from 'react-dom';
const element = <div>Hello, world</div>;
ReactDOM.render(
element,
document.getElementById('root')
);
なんか見慣れない構文が出てきましたね。。。
1つずつ解説していきます!
JSXとは?
上記でelementに格納された値は、JSXと呼ばれ、React要素を簡単に記述することのできる方法です。これにより、htmlをJsのなかに書いているような感覚で記述ができます。
実際にはReact.createElementに変換されていますので下記の文面は同義です。基本的にはJSXで書いていけば大丈夫です。
// JSX
const yesJsx = <div>Hello, world</div>;
// React.createElement
const noJsx = React.createElement('div', null, 'Hello World');
JSXで変数展開
JSX内では中括弧{}で囲むことで変数を展開することができます
const displayText = 'HelloWorld';
const HelloWorld = () => {
return (
<div>
<p>{ displayText }</p>
</div>
)
}
NGなJSXの例
JSXは基本的には一つのエレメントしか返すことができません。下記のようにreturnするエレメントが2つ以上あるとエラーとなります。
// エラーが出ます
import React from 'react';
const HelloWorld = () => {
return (
<div>
<p>HelloWorld</p>
</div>
<div>
<p>HelloWorld</p>
</div>
)
}
ただ、divのなかに囲ってあげると正常に動作します。
import React from 'react';
const HelloWorld = () => {
return (
<div>
<div>
<p>HelloWorld</p>
</div>
<div>
<p>HelloWorld</p>
</div>
</div>
)
}
複数の要素を返すことはできないのか?
実は、複数の要素を返す方法として**「Fragment(フラグメント)」**というものがあります。
ここではあまり詳しく言及はしませんが、実施に書いていると、複数の要素を返したい場合も出てくるので、その際はこの記法を活用することで解消することができます!
フラグメント – React
P.S @uitspitss さん、コメントいただきありがとうございます!
コンポーネントとは?
コンポーネントとは、UIの構成要素のことです。この部品を組み合わせて1つのページを作成していきます。実際はコンポーネント単位でjsファイルを作成し、importして呼び出すことが多いですが、今回はあまり気にせずに書いていきます。
例として、公式のチュートリアルにある三目ゲーム(⭕️❌ゲーム)のUIを例に説明します。下記の画像をご覧ください。
このようなUIがあったとして、Reactではこれを3つのコンポーネントに分けて考えます。1つはページ全体のGame、盤面を表すBoard、最後にマス目1つ1つを表すSquareです。Squareに関しては9つ存在することになります。
このような単位のことをコンポーネントと呼びます。コードに表すと下記のような感じです。
// 三目並べゲームのコンポーネント
import React from 'react';
// 盤面のマス1つ1つのコンポーネント
const Square = (props) => {
// 省略
}
// 盤面全体のコンポーネント
const Board = () => {
// 省略
}
// ページ全体のコンポーネント
const Game = () => {
// 省略
}
Tic Tac Toe
チュートリアル:React の導入 – React
stateとpropsについて
コンポーネントで使われる概念のうち、最初に覚えておきたいのがstateとpropsです。
- stateはコンポーネントの内部で制御される値のことです
- propsは親(呼び出し元)コンポーネントから受け取る値のことで基本読み取り専用になります
ちなみにpropsはpropertiesを略したものです。
この2つの値をコンポーネント間で受け渡す事で、複雑なUIを制御することができます
state
stateはコンポーネントの内部で制御される値のことです。そのため基本的には他のコンポーネントから制御できません。
また、stateが更新されると同時にコンポーネントの値が再レンダーされます。下記のコードでは、useStateというAPIを使う事でstateを管理しています。
下記の例ではBoard(盤面)コンポーネントにて9つのsquares(マス)の状態と、プレイヤーの順番の状態をstateで管理しています。
import React, { useState } from 'react'; // hooks
const Board = () => {
// コンストラクタ
const [squares, setSquares] = useState(Array(9).fill(null));
const [xIsNext, setXIsNext] = useState(true);
// 以下省略
}
propsを子コンポーネントに渡す
BoardコンポーネントからSquareコンポーネントを呼び出すときにvalueとonclickにpropsを渡しています。この時、変数だけでなく関数を渡す事もできます。
const Board = () => {
const squares = [0, 1, 2]
const handleClick = (i) {
// 省略
}
return (
<Square value={squares} onClick={() => handleClick(i)}/>
);
}
propsを受け取り、参照する
Squareコンポーネントは引数としてpropsを受け取ります。
props自体はオブジェクト構造となっており、props.xxxという記法で呼び出すことができます。下記の例ではvalueの中身の表示と、親コンポーネントの関数の実行をしています
const Square = (props) => {
return (
<button className="square" onClick={() => props.onClick()}>
{props.value}
</button>
);
}
ご参考 〜Reactで書く三目並べ(⭕️❌ゲーム)のコード〜
最終的なコードは下記になります。
公式のチュートリアル:React の導入 – Reactにも書かれているゲームのコードです。公式チュートリアルではコンポーネントの記法が少し古いため、Hooksで書き換えております。
import React, { useState } from 'react';
import ReactDOM from 'react-dom';
// controlled component
const Square = (props) => {
return (
<button className="square" onClick={() => props.onClick()}>
{props.value}
</button>
);
}
const Board = () => {
const [squares, setSquares] = useState(Array(9).fill(null));
const [xIsNext, setXIsNext] = useState(true);
const handleClick = (i) => {
const cloneSquares = squares.slice();
if (calculateWinner(cloneSquares) || cloneSquares[i]) {
return;
}
cloneSquares[i] = xIsNext ? 'X' : 'O';
setSquares(cloneSquares);
setXIsNext(!xIsNext);
}
const renderSquare = (i) => {
return (
<Square
value={squares[i]}
onClick={() => handleClick(i)}
/>
);
}
const winner = calculateWinner(squares);
let status;
if (winner) {
status = 'Winner: ' + winner;
} else {
status = 'Next player: ' + (xIsNext ? 'X' : 'O');
}
return (
<div>
<div className="status">{status}</div>
<div className="board-row">
{renderSquare(0)}
{renderSquare(1)}
{renderSquare(2)}
</div>
<div className="board-row">
{renderSquare(3)}
{renderSquare(4)}
{renderSquare(5)}
</div>
<div className="board-row">
{renderSquare(6)}
{renderSquare(7)}
{renderSquare(8)}
</div>
</div>
);
}
const Game = () => {
return (
<div className="game">
<div className="game-board">
<Board />
</div>
<div className="game-info">
<div>{/* status */}</div>
<ol>{/* TODO */}</ol>
</div>
</div>
);
}
const calculateWinner = squares => {
const lines = [
[0, 1, 2],
[3, 4, 5],
[6, 7, 8],
[0, 3, 6],
[1, 4, 7],
[2, 5, 8],
[0, 4, 8],
[2, 4, 6],
];
for (let i = 0; i < lines.length; i++) {
const [a, b, c] = lines[i];
if (squares[a] && squares[a] === squares[b] && squares[a] === squares[c]) {
return squares[a];
}
}
return null;
}
// ========================================
ReactDOM.render(
<Game />,
document.getElementById('root')
);
おさらい
- ReactはJavascriptのライブラリである
- Javascript(ES6)の構文がベースとなっている
- JSXという記法を使った仮想DOMを記述することができる
- コンポーネントベースでUIを生成する
- コンポーネントではstateとpropsを駆使して柔軟なUIを作成することができる
- stateはコンポーネント内部で制御する値のこと(外部から変更はできない)
- propsは基本参照のみだが、親コンポーネントの関数を渡すことができる
まとめ
少しでもReactに関心を持ってくだされば幸いです!