Lifecycle is the stages a component goes through from creation to removal.
Simple analogy: Imagine the component is a plant in a pot.
In functional components (with hooks) the lifecycle is managed through useEffect:
1. Mounting — component appeared (useEffect with []):
1useEffect(() => {2 // Executes ONCE after the first render3 fetchData();4}, []); // Empty array = only on mount
2. Updating — component updated (useEffect with [dependencies]):
1useEffect(() => {2 // Executes on every change of count3 console.log('count changed:', count);4}, [count]); // Array with dependencies
3. Unmounting — component is removed (return in useEffect):
1useEffect(() => {2 const timer = setInterval(() => console.log('tick'), 1000);34 return () => {5 clearInterval(timer); // Cleanup on component removal!6 };7}, []);
Complete lifecycle example:
1function UserProfile({ userId }) {2 const [user, setUser] = useState(null);3 const [status, setStatus] = useState("loading");45 // MOUNTING: runs once when component appears6 useEffect(() => {7 console.log("Component mounted");8 return () => console.log("Component will unmount");9 }, []);1011 // UPDATING: runs when userId changes12 useEffect(() => {13 let cancelled = false;14 setStatus("loading");15 fetch(`/api/users/${userId}`)16 .then(res => res.json())17 .then(data => {18 if (!cancelled) {19 setUser(data);20 setStatus("loaded");21 }22 });23 return () => { cancelled = true; }; // Cleanup24 }, [userId]);2526 if (status === "loading") return <Spinner />;27 return <h1>{user.name}</h1>;28}
How it works step by step:
useLayoutEffect runs (synchronous, before browser paints).useEffect runs (asynchronous, after browser paints).Performance considerations:
Important: