Preact Lifecycle Methods — Component Lifecycle in 3kB
In this tutorial, you will learn about Preact Lifecycle Methods. We cover key concepts, practical examples, and best practices to help you master this topic.
Learn Preact class component lifecycle methods, their React equivalents, and Preact-specific differences in mounting, updating, and unmounting phases.
In this lesson, you'll understand the component lifecycle in Preact: mounting, updating, and unmounting phases, and how they map to React's lifecycle.
What You'll Learn
The three lifecycle phases (mount, update, unmount), each available method's purpose, and how Preact's lifecycle differs from React's fiber-based approach.
Why It Matters
Lifecycle methods let you run code at specific points: fetching data after mount, cleaning up before unmount, or optimizing re-renders with shouldComponentUpdate.
Real-World Use
Durga Antivirus Pro's scan dashboard uses componentDidMount to fetch threat data, componentDidUpdate to animate new threats, and componentWillUnmount to cancel pending API requests.
flowchart TD
A[Mounting] --> B[constructor]
B --> C[componentWillMount - NOT supported]
C --> D[render]
D --> E[componentDidMount]
F[Updating] --> G[componentWillReceiveProps]
G --> H[shouldComponentUpdate]
H --> I[componentWillUpdate]
I --> J[render]
J --> K[componentDidUpdate]
L[Unmounting] --> M[componentWillUnmount]
style E fill:#673ab8,color:#fff
style K fill:#673ab8,color:#fff
style M fill:#673ab8,color:#fff
Mounting Phase
When a class component first appears in the DOM:
import { Component, render } from 'preact';
class DataLoader extends Component {
constructor(props) {
super(props);
this.state = { data: null, loading: true };
console.log('1. Constructor');
}
componentDidMount() {
console.log('3. Component mounted to DOM');
// Fetch data after component is in the DOM
setTimeout(() => {
this.setState({ data: 'Loaded data', loading: false });
}, 1000);
}
render() {
console.log('2. Render');
if (this.state.loading) return <p>Loading...</p>;
return <p>Data: {this.state.data}</p>;
}
}
Output: Console shows "1. Constructor", "2. Render", then "3. Component mounted to DOM". After 1 second, the component re-renders with "Data: Loaded data".
Updating Phase
When props or state change:
class Logger extends Component {
shouldComponentUpdate(nextProps, nextState) {
// Only update if the id prop changed
console.log('Should update?', nextProps.id !== this.props.id);
return nextProps.id !== this.props.id;
}
componentDidUpdate(prevProps) {
if (prevProps.id !== this.props.id) {
console.log(`ID changed from ${prevProps.id} to ${this.props.id}`);
// Fetch new data for the new ID
}
}
render() {
return <div>Current ID: {this.props.id}</div>;
}
}
Output: When id changes, shouldComponentUpdate returns true, the component re-renders, and componentDidUpdate logs the change.
Unmounting Phase
Cleanup before the component is removed:
class Timer extends Component {
componentDidMount() {
this.interval = setInterval(() => {
console.log('Tick');
}, 1000);
}
componentWillUnmount() {
clearInterval(this.interval);
console.log('Timer cleaned up');
}
render() {
return <p>Timer running...</p>;
}
}
function App() {
const [show, setShow] = useState(true);
return (
<div>
{show && <Timer />}
<button onClick={() => setShow(!show)}>Toggle Timer</button>
</div>
);
}
Output: The timer ticks every second. When the "Toggle Timer" button hides it, componentWillUnmount clears the interval and logs "Timer cleaned up".
Lifecycle with Hooks
Functional components use hooks to replicate lifecycle behavior:
import { useState, useEffect } from 'preact/hooks';
function DataFetcher({ url }) {
const [data, setData] = useState(null);
// componentDidMount + componentDidUpdate + componentWillUnmount
useEffect(() => {
console.log('Effect runs after render');
fetch(url)
.then(res => res.json())
.then(setData);
// Cleanup function = componentWillUnmount
return () => {
console.log('Cleanup on unmount or before next effect');
};
}, [url]); // Only re-run when url changes
return <pre>{JSON.stringify(data, null, 2)}</pre>;
}
Output: The effect fetches data when url changes. The cleanup function runs before the next effect or on unmount.
Common Mistakes
- Using
componentWillMount: Preact doesn't supportcomponentWillMount. Use the constructor orcomponentDidMountinstead. - Calling
setStateincomponentDidUpdatewithout conditions: This causes an infinite loop. Always guard state updates with a condition. - Forgetting cleanup in
componentWillUnmount: Not clearing timers, subscriptions, or aborting fetch requests causes memory leaks. - Using
componentWillReceiveProps: Preact doesn't supportcomponentWillReceiveProps. UsecomponentDidUpdateorgetDerivedStateFromProps. - Overusing
shouldComponentUpdate: Preact is already fast. Only useshouldComponentUpdatewhen profiling shows unnecessary re-renders.
Practice Questions
What is the order of lifecycle methods on mount? Answer:
constructor->render->componentDidMount. Preact doesn't callcomponentWillMount.How do you clean up resources before unmounting? Answer: In class components, use
componentWillUnmount. In functional components, return a cleanup function fromuseEffect.What does
shouldComponentUpdatereturn by default? Answer:true. Returnfalseto skip the re-render for that update cycle.What causes an infinite loop in
componentDidUpdate? Answer: CallingsetStatewithout a condition. Every state update triggers anothercomponentDidUpdate.
Challenge
Build a component that fetches data from an API when mounted, displays a loading state, shows the data, and cancels the fetch request if the component unmounts before the response arrives.
Mini Project
Create a polling component that fetches a status endpoint every 5 seconds using setInterval in componentDidMount, displays the status, and cleans up the interval in componentWillUnmount. Add a start/stop toggle.
FAQ
What's Next
Learn about Preact Hooks Overview to understand the hooks API in Preact for functional component state and lifecycle.
Built by the developers of DodaTech
Doda Browser, DodaZIP & Durga Antivirus Pro