副作用?
Reactを勉強していて誰もが一度躓くのがこの言葉だと思います。
「副作用」
僕がこの言葉を聞いて思い浮かべるのは「薬の副作用」でした。風邪薬を飲んだら副作用で眠くなりますよというようなイメージです。
辞書にもこのように書かれていました。
副作用...薬物の、病気を治す作用とは別の、望んでいない作用。有害なことが多い。「―を伴う特効薬」
このイメージのまま次の文を読むと意味が分からないと思います。
副作用 (effect) フック により、関数コンポーネント内で副作用を実行することができるようになります
僕は最初、『???』となりました。
副作用の再定義
Reactでの副作用を理解するにはまず、今までの副作用の定義を忘れましょう。ReactはuseState
で状態を持ちます。
const [state, setState] = useState()
setState
をしてstate
を変えた時、ページをリロードせずとも自動的にstate
が変わりますよね。このstate
が変わる時Reactはページを再レンダーしています。そしてこの再レンダー時(≒state変更時)に実行させる処理が副作用です。
(こんな感じ)
const [state, setState] = useState()
useEffect(() => {
hukusayou(state)
},[])
const handleClick = () => {
setState('hoge')
}
const handleChange = () => {
setState('bar')
}
上記を見ていただければ、「なぜわざわざ再レンダー時に副作用を起こすのか?」ということも分かるかと思います。setState後に続けて副作用の処理を書くとなると次のようになります。
const [state, setState] = useState()
const handleClick = () => {
setState('hoge')
hukusayou(state)
}
const handleChange = () => {
setState('bar')
hukusayou(state)
}
このやり方でもstate変更時に実行させる処理、副作用を起こせています。しかし、一点問題があります。上記のコードはDRYでないですね。
hukusayou(state)
を複数回呼び出しています。hukusayou関数が「stateの変更時に実行させたいもの」であるのならuseEffect内に書くと良いです。
コードの捕捉
一応、上記のコードはもう一点問題があります。
const handleClick = () => {
setState('hoge')
hukusayou(state)
}
hukusayou関数をsetState後に呼び出しているのですが、hukusayouに渡しているstateはsetState前のstateです。setStateは非同期で動くのでこのようになっています。なのでstateではなく新しい値をそのままhukusayou関数に渡しましょう。
const handleClick = () => {
setState('hoge')
hukusayou('hoge')
}