React components have a lifecycle that allows you to control what happens at different stages of a component’s existence. Here’s a breakdown of the key lifecycle phases and methods:
1. Mounting Phase (Component Creation)
Class Components
constructor()
– Initializes state and binds methodsstatic getDerivedStateFromProps()
– Updates state based on props (rarely used)render()
– Returns JSX to displaycomponentDidMount()
– Runs after component is mounted to DOM (ideal for API calls, subscriptions)
class Example extends React.Component {
constructor(props) {
super(props);
this.state = { data: null };
}
componentDidMount() {
fetchData().then(data => this.setState({ data }));
}
render() {
return <div>{this.state.data}</div>;
}
}
Functional Components Equivalent
function Example() {
const [data, setData] = useState(null);
useEffect(() => {
fetchData().then(setData);
}, []); // Empty dependency array = runs once on mount
return <div>{data}</div>;
}
2. Updating Phase (Re-rendering)
Class Components
static getDerivedStateFromProps()
– Sync state to propsshouldComponentUpdate()
– Optimize by preventing unnecessary rendersrender()
– Re-renders JSXgetSnapshotBeforeUpdate()
– Capture DOM info before updatecomponentDidUpdate()
– Runs after update completes
class Example extends React.Component {
shouldComponentUpdate(nextProps, nextState) {
return nextProps.id !== this.props.id; // Only update if id changes
}
componentDidUpdate(prevProps) {
if (this.props.id !== prevProps.id) {
this.fetchData(this.props.id);
}
}
}
Functional Components Equivalent
function Example({ id }) {
const [data, setData] = useState(null);
useEffect(() => {
fetchData(id).then(setData);
}, [id]); // Re-runs only when id changes
return <div>{data}</div>;
}
3. Unmounting Phase (Component Removal)
Class Components
componentWillUnmount()
– Cleanup before removal (cancel timers, subscriptions)
class Example extends React.Component {
componentDidMount() {
this.timer = setInterval(() => {}, 1000);
}
componentWillUnmount() {
clearInterval(this.timer);
}
}
Functional Components Equivalent
function Example() {
useEffect(() => {
const timer = setInterval(() => {}, 1000);
return () => clearInterval(timer); // Cleanup function
}, []);
}
4. Error Handling
Class Components
static getDerivedStateFromError()
– Render fallback UI after errorcomponentDidCatch()
– Log error information
class ErrorBoundary extends React.Component {
state = { hasError: false };
static getDerivedStateFromError(error) {
return { hasError: true };
}
componentDidCatch(error, info) {
logErrorToService(error, info);
}
}
Functional Components Equivalent
(Requires class component for error boundaries – no hook equivalent yet)
Lifecycle Cheat Sheet
Phase | Class Method | Hook Equivalent |
---|---|---|
Mounting | componentDidMount() | useEffect(() => {}, []) |
Updating | componentDidUpdate() | useEffect(() => {}, [deps]) |
Unmounting | componentWillUnmount() | useEffect(() => { return cleanup }, []) |
State from Props | getDerivedStateFromProps() | useMemo , useState with props |
Performance Opt | shouldComponentUpdate() | React.memo , useMemo , useCallback |
Key Takeaways
- Class components use explicit lifecycle methods
- Functional components use
useEffect
to handle most lifecycle needs useEffect
combinescomponentDidMount
,componentDidUpdate
, andcomponentWillUnmount
- Error boundaries still require class components
- Modern React favors functional components with hooks