🎉
【React】useEffectでホットリロード時は期待する動作だが、ブラウザリロード時は違う
コード
pages/hotReload/index.tsx
import { useEffect, useState } from 'react'
import Child from '../../components/hotReload/Child'
export const App = () => {
const [greeting, setGreeting] = useState('hello')
const [str, setStr] = useState('')
useEffect(() => {
if (str === 'goodbye') {
const newGreeting = str
setGreeting(newGreeting)
}
}, [str])
// }, []) // だとhot reload時にしか動かない
return (
<div>
<p>{greeting}</p>
<Child setStr={setStr} />
</div>
)
}
export default App
components/hotReload/Child.tsx
import { useEffect } from 'react'
type Props = {
setStr: React.Dispatch<React.SetStateAction<string>>
}
export const Child = ({ setStr }: Props) => {
useEffect(() => {
const newStr = 'goodbye'
setStr(newStr)
}, [])
return <div></div>
}
export default Child
説明
期待する動作
ブラウザをリロードした時も、
ホットリロード時もgoodbyeと表示されてほしい。
期待する動作にならない場合
pages/hotReload/index.tsx
useEffect(() => {
if (str === 'goodbye') {
const newGreeting = str
setGreeting(newGreeting)
}
}, []) // 正しく動作するものは }, [str])
とする。
コードを編集して保存し、ホットリロードが走った時
期待通りの動作。
ブラウザをリロードした時
期待とは違う文言。
期待する動作をするコードに修正
pages/hotReload/index.tsx
useEffect(() => {
if (str === 'goodbye') {
const newGreeting = str
setGreeting(newGreeting)
}
}, [str])
とする。
そうすると、ブラウザをリロードしても、
期待通りuseEffectのマウントタイミングにstrが更新された時も含まれるようになる。
Discussion