This subject is very important for React Native or React developers, but recently I saw quite a number of React developers who do not use the wonderful thing called cleanup function in useEffect
hook, so I decided to write a post about that and show you my friends, a real-world example.
This article is for developers with a basic knowledge of the useEffect
hook function.
React allows us to create actions on the component mount or while the component is updated by the use of useEffect
hook with the array of dependencies.
It takes two parameters. The first parameter is a function. The second parameter is an array of dependencies. If any dependency changes, then the effect will run again.
//Run after component mounted/first rendered.
useEffect(()=>{},[])//Run after dep1 or dep2 change/updated.
useEffect(()=>{},[dep1, dep2])
The useEffect
function has one more responsibility, and this is for the cleanup function that runs after the component is unmounted.
//Run after component is unmounted/removed
useEffect(()=>{
return ()=>{}
},[])
This is the main question that we need to ask ourselves before using it because we need to know its exact purpose.
This cleanup function that useEffect
offers us is for letting us clean or remove any processes or actions that are not relevant when the component is unmounted or not shown anymore.
Example for action that runs after the component is unmounted.
//When the component will unmounted,
//The console will print "Component unmounted"useEffect(()=> {
return ()=> {
console.log("Component unmounted");
}
},[])
Real World Example
I will illustrate the importance of the cleanup function with a real-world example that can prevent leak of memory and bad performance.
Let’s assume that we have an application to which we want to add a new component that shows the loading text with 3 dots that builds the dots one after another until we receive the response from the server.
For example:
“Loading” and after 1 sec -> “Loading.” and after 1 sec -> “Loading..” and after 1 sec -> “Loading…” and so on until we receive the response from the API request.
This component will include the useEffect
hook with the cleanup function, let’s build the component.
const Loading = ()=> {
const [dots, setDots] = useState<string>(".");
const dotsLoading = () => {
setDots((state)=>(state.length === 3 ? '' : `${state}.`));
};useEffect(() => {
//1000 ms = 1 sec
const 1Sec = 1000;
const intervalId = setInterval(dotsLoading, 1Sec);
return () => clearInterval(intervalId);
}, []);return (
<View style={Styles.modal}>
<Text>Loading{dots}</Text>
</View>
)
}
This Loading
component now can be included in any screen component that makes an API request and shows this Loading
component while it fetches/post data from/to the server.
This Screen
component will contain an API request to show the Loading component while we wait for the data to be received from the server.
Let’s build the component.
import Loading from "./components/Loading;
import { fetchData } from "./API;const Screen = ()=> {
const [isLoading, setIsLoading] = useState<boolean>(false); useEffect(()=>{
setIsLoading(true);
(
async ()=>{
const result = await fetchData();
setIsLoading(false);
}
)();
},[])return (
<View>
{isLoading && <Loading />}
</View>
)
}
As you can see, we have Screen
component that on mount creates an API request with fetchData
function inside useEffect
.
In the beginning, we make the Loading
component visible and now the Loading
component is shown until we receive the data from the server, in addition, the async function is to await for the fetchData
function response.
When the isLoading
parameter is false, the cleanup function inside the Loading
component is run and it clears the interval and stops the loop. By doing it this way, we protect our app from running the dotsLoading
function even if we no longer use the Loading
component (when we receive the data from the API request).
The cleanup function of useEffect
is very powerful and with a good understanding of it, we can save our application from bad performance and memory leakage.
Source: JavaScript in Plain English