RReactJS is the leading frontend framework. They recently released a new way to write React components using a function instead of class. This new method allows developers to keep the ease of function and still have the deepness of React lifecycle by using hooks.
Let’s see how to use the useEffect
hook.
The problem raised here is that if you try to fetch a value and update a state directly in the same function, it will probably not work. To showcase that, we will try to show the information of the Planet Tatooine fetched from a fabulous Star Wars database.
import React, { useState } from "react"; const starWarsPlanetInfo = () => { const [planetInfo, setPlanetInfo] = useState({}); fetch("https://swapi.dev/api/planets/1/") .then(response => response.json()) .then(data => setPlanetInfo(data)); return ( <div> {planetInfo.name} </div> ); }; export default starWarsPlanetInfo;
Unfortunately, this will not work because an infinite loop will be triggered. The function will fetch the data from Swapi, and then update the state that will … trigger a re-render of the component, which will restart the function. Let’s see how to avoid that infinite loop.
We have to use the useEffect
hook to implement reactive code here.
import React, { useState } from "react"; const starWarsPlanetInfo = () => { const [planetInfo, setPlanetInfo] = useState({}); useEffect(() => { fetch("https://swapi.dev/api/planets/1/") .then(response => response.json()) .then(data => setPlanetInfo(data)); }, []); return ( <div> {planetInfo.name} </div> ); }; export default starWarsPlanetInfo;
useEffect
takes a function as a first argument that will trigger once the component has been rendered. The second argument is an array where you can add values used by your component (state, props). useEffect
will watch those values, and each time they change it will relaunch the first function passed as an argument.
The useEffect
will run only once with the empty array we passed before. If we give no second argument, it will run every time.
useEffect
can listen to state change and then launch a function. To do so, we have to pass state as the second argument of the function:
const counter = ()=> { const [counter, setCounter] = useState(0); useEffect(() => { console.log("count changed!"); }, [counter]); return ( <div> {count1} <br /> <button onClick={() => setCount1(count1 + 1)}>Increment count1</button> </div> ); }
useEffect
can also listen to props change and then launch a function. To do so, we have to pass React props as the second argument of the function:
const counterNumber = ({ counterProps }) => { useEffect(() => { console.log(`counter value : ${counterProps}`); }, [counterProps]); return ( <div> Counter : {counterProps} </div> ); } const counterApp =() => { const [counter, setCounter] = useState(0); return ( <div> <PropChangeWatch counterProps={counter} /> <button onClick={() => setCount1(count1 + 1)}>Increment count1</button> </div> ); }
useEffect
hook is used in many situations; it’s beneficial because it doesn’t block the screen, allowing a seamless experience for the user. However, the useEffect
hook should not be used in React for DOM mutation visible to the user. For that, it’s better to use the useLayoutEffect
hook provided by React.