TL;DR
よいしょ……よいしょ……
useEffect便利ですよね。
stateの変化を監視し、そのstateの変化に伴うべき処理の流れを一元管理できます。
import React, { useState, useEffect } from 'react'
import ReactDOM from 'react-dom'
function Counter(props) {
const [count, setCount] = useState(0)
const [lastUpdatedAt, setLastUpdatedAt] = useState(null)
useEffect(() => {// 『count』 が更新された際に、それに伴い必ず実行される
setLastUpdatedAt(new Date().toString())
}, [count])
return (
<div>
<p>カウント {count} 回目</p>
{/* 変な要件の機能だなぁ…🤔 */}
<p>🎉最終カウントアップ日時🎉 {lastUpdatedAt || ''} </p>
<p>
<button onClick={() => setCount(count + 1)}>カウントアップ</button>
</p>
</div>
)
}
ReactDOM.render(
<Counter />,
document.getElementById('root')
)
かなしいところ
(上記例の様に)何も考えずそのまま使うと、対象のstateが変更されているか否かに関わらず、初回レンダー時『にも』必ず動いてしまう。
カウントまだ1回もしてないのに「最終カウントアップ日時」出てんのおかしいダルルォン!?(うるさいですね・・・)
かいけつ
useRefを使う。
import React, { useState, useEffect, useRef } from 'react'
import ReactDOM from 'react-dom'
function Counter(props) {
const [count, setCount] = useState(0)
const [lastUpdatedAt, setLastUpdatedAt] = useState(null)
const isFirstRender = useRef(false)
useEffect(() => { // このeffectは初回レンダー時のみ呼ばれるeffect
isFirstRender.current = true
}, [])
useEffect(() => {// 『count』 が更新された場合『と』初回レンダー時に動くeffect
if(isFirstRender.current) { // 初回レンダー判定
isFirstRender.current = false // もう初回レンダーじゃないよ代入
} else {
setLastUpdatedAt(new Date().toString())
}
}, [count])
return (
<div>
<p>カウント {count} 回目</p>
<p>🎉最終カウントアップ日時🎉 {lastUpdatedAt || ''} </p>
<p>
<button onClick={() => setCount(count + 1)}>カウントアップ</button>
</p>
</div>
)
}
ReactDOM.render(
<Counter />,
document.getElementById('root')
)
かつてのクラスコンポーネントで言う所の「componentDidUpdate」と似た働きが期待出来ます。
けつろん
結果オーライ! 終わりやっぱりReactはたのしい。以上。