Table of Contents
If you have created a new project recently using Create React App or upgraded to React version 18, you will see that the useEffect hook gets executed twice in development mode.
If you are new to useEffect hook, you can read one of my previous articles: a complete guide to useEffect hook.
Replicating the issue
Create a new react app using the following command:
1npx create-react-app react-use-effect-twice
Update App.js
with the following code:
1import { useEffect } from "react"23function App() {4 useEffect(() => {5 console.log("useEffect executed (component mounted)")6 }, [])78 return <div className="App"></div>9}1011export default App
Here we have a useEffect hook and we are logging a message inside it.
If you run the application and open the browser console, you will see the message is being displayed twice.
Understanding the issue
In StrictMode, starting from React 18, in development mode, the effects will be mounted, unmounted, and mounted again.
This happens only in development mode, not in production mode.
This was added to help React in the future to introduce a feature where it can add or remove a section of the UI while preserving the state. For example, while switching between tabs, preserving the state of the previous tab helps in preventing unnecessary execution of effects like API calls.
We can confirm the behavior by adding a cleanup function to the useEffect hook:
1import { useEffect } from "react"23function App() {4 useEffect(() => {5 console.log("useEffect executed (component mounted)")6 return () => {7 console.log("useEffect cleanup (component unmounted)")8 }9 }, [])1011 return <div className="App"></div>12}1314export default App
If you run the application, you will see the following messages in the browser console:
Fixing the issue
If you have read the previous section, this is not really an issue. Hence it doesn't need any fixing.
If you still want to avoid useEffect being called twice, you can remove the <StickMode>
tag from the index.js
file.
Do follow me on twitter where I post developer insights more often!