//tips
//smart contract
続いてボタンクリックでメッセージを表示し、表示内formの入力内容に名前を記入することで、元のページの内容を変更して表示する。
import React, { useState } from 'react'
import './App.css'
function AlertMessage(props) {
return <div className="alert alert-primary h5 text-primary">
{props.message}
</div>
}
function CardMessage(props) {
return <div className="card p-3 h5 border-primary text-center">
{props.message}
</div>
}
function App() {
const [msg, setMsg] = useState("This is sample messsage!")
const doAction = ()=>{
let res = window.prompt('type your name:')
setMsg("Hello, " + res + "!!")
}
return (
<div>
<h1 className="bg-primary text-white display-4 ">React</h1>
<div className="container">
<h4 className="my-3">Hooks sample</h4>
<AlertMessage message={msg} />
<CardMessage message={msg} />
<div className="text-center">
<button onClick={doAction} className="btn btn-primary">
Click me!
</button>
</div>
</div>
</div>
)
}
export default App
window.promptはjsの標準機能でテキストを入力するダイアログを表示するもの。入力した値を戻り値として返し、それをsetMsgでmsgステージに設定する。
ここでは <AlertMessage message={msg} />のように属性値をステートで指定しておくことで、propsを使い、各コンポーネントで編集ができるようにしていた。
各コンポーネントから値をあげる方法も考える。
import React, { useState } from 'react'
import './App.css'
function AlertMessage(props) {
const data = ["Hello!", "Welcome...", "Good-bye?"]
const actionAlert = ()=> {
const re = data[Math.floor(Math.random() * data.length)]
props.setAlert('message: "' + re + '".')
}
return <div className="alert alert-primary h5 text-primary">
<h5>{props.alert}</h5>
<button onClick={actionAlert} className="btn btn-primary">
Click me!
</button>
</div>
}
function CardMessage(props) {
const [count, setCount] = useState(0)
const actionCard = () => {
setCount(count + 1)
props.setCard("card counter: " + count + " count.")
}
return <div className="card p-3 border-dark text-center">
<h5>{props.card}</h5>
<button onClick={actionCard} className="btn btn-secondary">
Click me!
</button>
</div>
}
function App() {
const [alert, setAlert] = useState("This is alert messsage!")
const [card, setCard] = useState("This is card messsage!")
return (
<div>
<h1 className="bg-primary text-white display-4 ">React</h1>
<div className="container">
<h4 className="my-3">Hooks sample</h4>
<AlertMessage alert={alert} setAlert={setAlert} />
<CardMessage card={card} setCard={setCard} />
<hr />
<div className="text-right">
<p>{alert}</p>
<p>{card}</p>
</div>
</div>
</div>
)
}
export default App
このようにステート変数とステート変更関数を一緒に渡していることがわかる。
<AlertMessage alert={alert} setAlert={setAlert} />
<CardMessage card={card} setCard={setCard} />
このsetAlartなどをコンポーネントから呼び出し、値を変更することで、一緒にalertの方も更新される。
今度はサーバにアクセスしてデータを取得するような更新の際に必要な処理の対処法も確認する。今まではフォームに記入するなど、フロントエンドで完結していたがバックエンドも絡めて考える。
その際に使用するのがuseEffectという副作用フックと呼ばれるもの。これをコンポーネントが更新された際に指定の関数を引数にして実行させれば良い。
下記のようにdoChangeでvalの値が更新されると、コンポーネントが更新され、それによりuseEffectで設定された関数が自動的に呼び出され計算結果が表示されている。このコンポーネントの更新という考え方には習熟しておく必要がありそう。
function App() {
const [val, setVal] = useState(0)
const [msg, setMsg] = useState('set a number...')
const doChange = (event) => {
setVal(event.target.value)
}
useEffect(() => {
let total = 0
for (let i = 0;i <= val;i++) {
total += i
}
setMsg("total: " + total + ".")
})
return (
<div>
<h1 className="bg-primary text-white display-4 ">React</h1>
<div className="container">
<h4 className="my-3">Hooks sample</h4>
<AlertMessage msg={msg} />
<div className="form-group">
<label>Input:</label>
<input type="number" className="form-control"
onChange={doChange} />
</div>
</div>
</div>
)
}
このuseEffectの利用でdoChangeの内容がかなりシンプルに描けるようになった。
また、複数useEffectの更新による無限呼び出しを避けるために、第二引数に更新の際に呼び出しを実行する対象を指定することができる。
下記のようにtax1,tax2が更新されたら、こちらは実行される。
useEffect(() => {
let res = <div>
<p>軽減税率(8%) : {tax1} 円</p>
<p>通常税率(10%): {tax2} 円</p>
</div>
setMsg(res)
}, [tax1, tax2])
次に関数コンポーネントないに既存のフックを使って機能を実装するのではなく、機能そのものをオリジナルフックとして生成する方法で考える。
オリジナルフックはuseで始まる関数を作成すれば良いという非常に簡単なもの。
下記のようなものがそれに当たる。
function useCounter() {
const [num, setNum] = useState(0)
const count = ()=>{
setNum(num + 1)
}
return [num, count]
}
これをもとにページを作成していくと、 useCounter() をAlertMessage(props) 内部でステートとして扱い、その変更関数として実行することで表示反映に干渉できる。
import React, { useState, useEffect } from 'react'
import './App.css'
function useCounter() {
const [num, setNum] = useState(0)
const count = ()=>{
setNum(num + 1)
}
return [num, count]
}
function AlertMessage(props) {
const [counter, plus] = useCounter()
return <div className="alert alert-primary h5 text-center">
<h4>count: {counter} .</h4>
<button onClick={plus} className="btn btn-primary">
count</button>
</div>
}
function App() {
return (
<div>
<h1 className="bg-primary text-white display-4 ">React</h1>
<div className="container">
<h4 className="my-3">Hooks sample</h4>
<AlertMessage />
</div>
</div>
)
}
export default App