React 18 useEffect behavior
A significant change that broke things was introduced in React 18: while Strict Mode is active, all components mount and unmount before being remounted again.
Because this is done to provide the groundwork for a feature that isn't currently available in React, there is no necessity to do this for the current version of React v18.
This means that each component is mounted, then unmounted, and then remounted and that a useEffect call with no dependencies will be run double-time when it is used in React in version 18.
We can confirm the behavior by using the cleanup function of the useEffect hook.
If we used the useEffect hook as follows:
useEffect(() => {
console.log("First call on mount..");
return () => console.log("Cleanup..");
}, []);
The output to the console should look like this:
First call on mount..
Cleanup..
First call on mount..
Now what if we need to use the useEffect
hook to fetch data, so that it does not fetch twice?
One easy solution to this behavior is to disable strict mode.
Open the src/index.js
file and remove the StrictMode
higher order component:
import React, { StrictMode } from 'react';
import { createRoot } from 'react-dom/client';
import App from './App';
const rootElement = document.getElementById('root');
const root = createRoot(rootElement);
root.render(
<StrictMode>
<App />
</StrictMode>
);
Conclusion
Beginning with React 18, when in development mode, the components will be mounted, unmounted, and then mounted once again in StrictMode.
This only occurs in the development mode; it does not occur in the production mode.
This was introduced so that in the future, when React decides to offer a feature that allows it to add or delete an area of the UI while still maintaining the state, this will help it do so. For instance, when moving between tabs, maintaining the state of the preceding tab might assist avoid the execution of effects such as API calls that are not essential.