
Reactではfetchを使用時に2回リクエストする
Reactではfetchを使用時にdev(開発)環境だとStrictModeが使用されている場合は2回リクエストが発生します。
App.tsx
import { useEffect } from 'react'
function App() {
useEffect(() => {
fetch('https://dummyjson.com/test')
.then(res => res.json())
.then(data => {
console.log(data)
// {status: 'ok', method: 'GET'}
// {status: 'ok', method: 'GET'}
})
}, [])
return <h1>fetch sample</h1>
}
export default App
StrictModeが使用されている場合は2回リクエストが発生するのは正常な動作ですが、コードによっては1回のリクエストで済ませたい場合もあります。
そんなときはuseEffect内でreturn () => {} (クリーンアップ) を使用してフラグを追加して以下のコードにすればリクエストが1回で済みます。
App.tsx
import { useEffect } from 'react'
function App() {
useEffect(() => {
let isFetch = false
fetch('https://dummyjson.com/test')
.then(res => res.json())
.then(data => {
if (!isFetch) {
console.log(data)
// {status: 'ok', method: 'GET'}
}
})
return () => { isFetch = true }
}, [])
return <h1>fetch sample</h1>
}
export default App
クリーンアップはconsole.logを1回だけ出したいケースでも使えます。
App.tsx
import { useEffect } from 'react'
function App() {
useEffect(() => {
return () => console.log('Hello')
}, [])
return <h1>fetch sample</h1>
}
export default App
useRefで初回のみ実行する
useRefを使用して初回レンダリングのフラグを設定することでも初回レンダリング時のみ実行できます。
一般的にはこちらのやり方のほうが主流です。
App.tsx
const isInitialRender = useRef(true)
useEffect(() => {
if (isInitialRender.current) {
isInitialRender.current = false
// 初回レンダリング時のみ実行する処理
}
}, [])
ReactのStrictModeでコンポーネントが2回レンダリングされるのは副作用が正しく動作されているか確認するためなので、特別な理由がなければ使わないようにしてください。