Lifecycle
Run code when components mount and unmount. Set up subscriptions, fetch data, and clean up resources.
onMount
Run code once when a component first renders:
import { onMount } from 'what-framework';
function Chart({ data }) {
let canvas;
onMount(() => {
// Component is now in the DOM
// canvas ref is available
const chart = new Chart(canvas, { data });
console.log('Chart initialized');
});
return <canvas ref={el => canvas = el} />;
}
Use onMount for:
- DOM measurements (element sizes, positions)
- Setting up third-party libraries
- Initial data fetching
- Animations on enter
onCleanup
Register cleanup code to run when the component unmounts:
import { onMount, onCleanup } from 'what-framework';
function WebSocketChat({ roomId }) {
let socket;
onMount(() => {
socket = new WebSocket(`wss://chat.example.com/${roomId}`);
socket.onmessage = (e) => {
console.log('Message:', e.data);
};
});
onCleanup(() => {
// Close connection when component unmounts
socket?.close();
});
return <div className="chat">...</div>;
}
Use onCleanup for:
- Removing event listeners
- Closing connections (WebSocket, EventSource)
- Clearing timers/intervals
- Canceling pending requests
- Cleaning up third-party library instances
Common Patterns
Event Listeners
function WindowSize() {
const size = signal({ width: 0, height: 0 });
onMount(() => {
const updateSize = () => {
size.set({
width: window.innerWidth,
height: window.innerHeight,
});
};
updateSize();
window.addEventListener('resize', updateSize);
});
onCleanup(() => {
window.removeEventListener('resize', updateSize);
});
return <p>{() => `${size().width} x ${size().height}`}</p>;
}
Timers
function Clock() {
const time = signal(new Date());
onMount(() => {
const id = setInterval(() => {
time.set(new Date());
}, 1000);
// Return cleanup directly from onMount
return () => clearInterval(id);
});
return <p>{() => time().toLocaleTimeString()}</p>;
}
Third-Party Libraries
function Map({ lat, lng }) {
let container;
let map;
onMount(() => {
map = L.map(container).setView([lat, lng], 13);
L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png').addTo(map);
});
onCleanup(() => {
map?.remove();
});
return <div ref={el => container = el} style={{ height: '400px' }} />;
}
useEffect Alternative
For React-style lifecycle, use useEffect:
import { useEffect } from 'what-framework';
function Profile({ userId }) {
const user = signal(null);
// Runs on mount and when userId changes
useEffect(() => {
fetch(`/api/users/${userId}`)
.then(r => r.json())
.then(data => user.set(data));
// Cleanup (optional)
return () => {
console.log('Cleanup');
};
}, [userId]); // Dependencies
return <div>{() => user()?.name}</div>;
}
Comparison
| API | When to Use |
|---|---|
onMount |
Setup that runs once on mount |
onCleanup |
Cleanup that runs on unmount |
useEffect |
React-style effect with dependencies |
effect |
Reactive effect (auto-tracks signals) |
Which to choose?
Use onMount/onCleanup for one-time setup. Use effect for reactive side effects that depend on signals. Use useEffect for React compatibility.