react 入門 2
カウンターをコンポーネントで作ろう
ボタンを押すと、カウントアップするカウンターを関数コンポーネントで作りましょう。
初めに、関数コンポーネントでのユーザーのボタンクリック時にイベントの扱いと、コンポーネント内部でカウントを保持する方法を学ぶことができます。
まずは通常のhtmlとES6での例を示します。
index.html
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8"/>
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>test2</title>
</head>
<body>
<div id = "root"></div>
<script type="module" src="./index.js"></script>
</body>
</html>
id = "root"のdiv要素の定義と、index.js呼び出しをするだけのhtmlです。
index.js
import { Counter } from "./counter.js"
let counter = new Counter("root")
ES6で定義したカウンタモジュールを生成しているだけです。
counter.js
export class Counter{
constructor(areaId){
//親要素(このコンポーネントを表示する位置のタグidの要素)を取得
this.topElm = document.getElementById(areaId)
//コンポーネント内部に保持するカウンタ
this.count = 0
//コンポーネントを構成する要素。
//それぞれの要素にはidをつけ、要素のプロパティを操作するスタイル
this.html_counter =`
<p id ="showCnt"></p>
<button id="cntUp" >count up</button>
`;
//親要素とコンポーネント構成要素のバインド
this.topElm.innerHTML = this.html_counter
//P要素にカウント値を設定
this.showCnt_p = document.getElementById("showCnt")
this.showCnt_p.innerText = `count = ${this.count}`
//ボタン要素にイベントを設定
this.cntUp_button = document.getElementById("cntUp")
this.cntUp_button.addEventListener("click",e =>{this.countup(e)} )
}
//ボタンがクリックされた時に呼ばれる関数
countup(e){
//カウンタをカウントアップ
this.count += 1
//P要素にカウント値を反映
this.showCnt_p.innerText = `count = ${this.count}`
}
}
カウンタモジュールをクラスで定義しています。カウンタ変数をthis.countで保持していることと、内部でモジュールを構成する要素のDOMを取得して書き換えたりイベントを追加したりしています。詳しくはコメントに記載しています。
ユーザのアクションイベントを受け取る
reactのJSX でイベントを受け取るときには、次のようにします。
<要素 イベントハンドラプロパティ={関数}>要素に表示する文字</要素>
要素
buttonやdivやimgなどです。
イベントハンドラプロパティ
下記のリファレンスからhtmlの個別のイベントの詳細が見れます。
たとえばclickイベントのリファレンスを見てみるとイベントハンドラプロパティとして、onclick が記載せされています。
reactでは、イベントハンドラプロパティをキャメルケースで著します。
onclickはonClickとなります。以下に例を示します。
関数
イベントハンドラとして定義した関数名を{}で括ります。
<button onClick={handleClick}> click me </button>
コンポーネントごとに情報を保持させる
関数コンポーネントは、読み取り専用のpropsを受け取り表示などに活用できましたが、コンポーネント内部で値を保持できる変数は、useStateを使って宣言します。
const [状態変数, 状態を変更するための関数] = useState(状態の初期値)
useStateは内部変数の初期値を受け取り、内部変数となる変数と、その内部変数をその後変更する関数を返します。ちなみにconst を使っていますが、配列の名前が変えられないだけで、中身の書き換えはできます。
たとえば下記のように定義、使用します。
const [count, setCount] = useState(0)
setCount(10)
const [text, setText] = useState("hello")
コンポーネントには複数の変数を定義できます。数値、文字列、オブジェクトなど様々な型を扱えます。
react関数コンポーネントでのカウンタの実装
reactでのイベントの使い方とuseStateの使い方を学びましたので、カウンタを関数コンポーネントで実装します。index.htmlとindex.jsは前回で説明した通りのシンプルなものです。
index.html
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>test</title>
</head>
<body>
<div id="root"></div>
</body>
</html>
index.js
import React, { StrictMode } from 'react'
import ReactDOM from 'react-dom/client'
import Counter from './Counter'
const root = ReactDOM.createRoot(document.getElementById('root'))
root.render(
<StrictMode>
<Counter initCount={0}/>
</StrictMode>
)
Conterコンポーネントを呼び出しています。initCountは、Counterコンポーネントのカウンタの初期値として与えるpropsです。
Counter.js
import { useState } from "react"
const Counter = (prop) => {
const [count,setCount] = useState(prop.initCount)
const countup = () => {
setCount(count + 1)
}
return(
<div>
<p>count = {count}</p>
<button onClick={countup}>count up</button>
</div>
)
}
export default Counter
useStateをimport していることに注意してください。
また、countup関数で、countの値を更新する際には、setCountを使用しています。つまり、count変数自体は読み取り専用の変数のように扱います。