Why is my React useEffect Hook running twice on page load? #91205
-
SummaryI am building a Next.js / React application, and I have a useEffect hook that fetches data from an API when the component mounts using the empty dependency array []. However, when I look at my console logs, I can see that the fetch request is firing two times instead of just once whenever I load the page. Is this a bug in React, or am I doing something wrong with my hook? Additional informationNo response ExampleNo response |
Beta Was this translation helpful? Give feedback.
Replies: 1 comment 1 reply
-
|
This is actually the intended behavior in React 18 when you are in development mode! React automatically wraps your application in <React.StrictMode>. In development, Strict Mode unmounts and remounts every component automatically whenever it is rendered for the first time. This is done on purpose to help you find bugs related to side effects and to ensure your useEffect cleanup functions are working properly. How to handle it: Option 1 (Recommended): Add a cleanup function Make sure your effect cleans up after itself (e.g., aborting a fetch request): javascript fetch('/api/data', { signal: controller.signal }) return () => controller.abort(); // Cleanup Note: The double execution only happens in development. When you build and deploy to production, the useEffect will only run once! |
Beta Was this translation helpful? Give feedback.
This is actually the intended behavior in React 18 when you are in development mode!
React automatically wraps your application in <React.StrictMode>. In development, Strict Mode unmounts and remounts every component automatically whenever it is rendered for the first time. This is done on purpose to help you find bugs related to side effects and to ensure your useEffect cleanup functions are working properly.
How to handle it:
Option 1 (Recommended): Add a cleanup function Make sure your effect cleans up after itself (e.g., aborting a fetch request):
javascript
useEffect(() => {
const controller = new AbortController();
fetch('/api/data', { signal: controller.signal })
.then(res => res.j…