Component Lifecycle
MedFunctional components have a lifecycle managed through hooks. A component mounts when it first appears in the tree, updates when its state or props change, and unmounts when removed. useEffect's setup and cleanup functions map to these phases, replacing class lifecycle methods.
Interactive Visualization
Key Points
- Mount: component appears in the tree, initial render occurs
- Update: re-render triggered by state change, prop change, or parent re-render
- Unmount: component removed from the tree, cleanup runs
- useEffect setup runs after mount and after every update matching dependencies
- useEffect cleanup runs before the next effect and on unmount
- StrictMode double-invokes effects in development to detect impure code
- Think in terms of synchronization, not lifecycle events
Code Examples
Lifecycle with useEffect
import { useState, useEffect } from 'react' function ChatRoom({ roomId }: { roomId: string }) { const [messages, setMessages] = useState<string[]>([]) useEffect(() => { // Setup: runs on mount and when roomId changes const connection = createConnection(roomId) connection.on('message', (msg: string) => { setMessages((prev) => [...prev, msg]) }) // Cleanup: runs before re-connecting and on unmount return () => { connection.disconnect() } }, [roomId]) return ( <ul> {messages.map((msg, i) => <li key={i}>{msg}</li>)} </ul> ) } function createConnection(roomId: string) { return { on: (_event: string, _cb: (msg: string) => void) => {}, disconnect: () => {}, } }
When roomId changes, cleanup disconnects from the old room before setup connects to the new room, preventing leaked connections
Mount-Only and Unmount Logic
import { useEffect, useRef } from 'react' function AnimatedComponent() { const elementRef = useRef<HTMLDivElement>(null) useEffect(() => { // Mount: initialize animation library const animation = startAnimation(elementRef.current) return () => { // Unmount: clean up animation animation.destroy() } }, []) // Empty deps: mount + unmount only return <div ref={elementRef}>Animated content</div> } function startAnimation(_el: HTMLDivElement | null) { return { destroy: () => {} } }
An empty dependency array makes the effect run only on mount with cleanup only on unmount, similar to componentDidMount and componentWillUnmount
Common Mistakes
- Thinking in lifecycle methods instead of effect synchronization
- Not understanding that effects run after render, not during
- Missing cleanup for subscriptions causing memory leaks after unmount
Interview Tips
- Map class lifecycle methods to hooks: componentDidMount -> useEffect with [], componentDidUpdate -> useEffect with deps
- Explain the shift from lifecycle thinking to synchronization thinking
- Discuss how StrictMode double-mounting helps catch missing cleanups