In React functional components, what does the useEffect hook mainly do?
Think about tasks that happen after the component shows on screen, like loading data or setting timers.
useEffect runs code after the component renders. This is useful for side effects such as fetching data, setting up subscriptions, or changing the DOM outside React's normal flow.
Consider this React code snippet:
useEffect(() => { console.log('Effect ran'); }, []);When will this effect run?
useEffect(() => { console.log('Effect ran'); }, []);Empty array means no dependencies to watch for changes.
When the dependency array is empty, useEffect runs only once after the first render, similar to componentDidMount in class components.
What will be logged to the console when this component runs?
import React, { useState, useEffect } from 'react';
function Counter() {
const [count, setCount] = useState(0);
useEffect(() => {
setCount(count + 1);
console.log(count);
});
return <div>Count: {count}</div>;
}import React, { useState, useEffect } from 'react'; function Counter() { const [count, setCount] = useState(0); useEffect(() => { setCount(count + 1); console.log(count); }); return <div>Count: {count}</div>; }
Think about what happens when state changes inside useEffect without dependencies.
Without a dependency array, useEffect runs after every render. Calling setCount inside it updates state, causing another render, which triggers useEffect again. This creates an infinite loop logging increasing counts starting from 0.
Examine this React code:
useEffect(() => {
const id = setInterval(() => console.log('Tick'), 1000);
return () => clearInterval(id + 1);
}, []);Why does the interval not clear properly when the component unmounts?
useEffect(() => {
const id = setInterval(() => console.log('Tick'), 1000);
return () => clearInterval(id + 1);
}, []);Check the argument passed to clearInterval.
The interval ID returned by setInterval must be passed exactly to clearInterval. Adding 1 changes the ID, so the interval is never cleared, causing it to keep running.
Given this component:
function Example() {
useEffect(() => {
console.log('Effect 1');
return () => console.log('Cleanup 1');
}, []);
useEffect(() => {
console.log('Effect 2');
return () => console.log('Cleanup 2');
});
return <div>Example</div>;
}What is the correct sequence of console logs when the component mounts and then unmounts?
function Example() { useEffect(() => { console.log('Effect 1'); return () => console.log('Cleanup 1'); }, []); useEffect(() => { console.log('Effect 2'); return () => console.log('Cleanup 2'); }); return <div>Example</div>; }
Remember that effects run in order, but cleanups run in reverse order.
On mount, effects run in the order they appear: Effect 1 then Effect 2. On unmount, cleanup functions run in reverse order: Cleanup 2 then Cleanup 1.