useUnmount
React hook for running cleanup logic when a component unmounts. Perfect for React applications requiring cleanup tasks like canceling subscriptions with Next.js integration and TypeScript support.
Installation
npx shadcn@latest add https://www.shadcn.io/registry/use-unmount.json
npx shadcn@latest add https://www.shadcn.io/registry/use-unmount.json
pnpm dlx shadcn@latest add https://www.shadcn.io/registry/use-unmount.json
bunx shadcn@latest add https://www.shadcn.io/registry/use-unmount.json
Features
- Unmount cleanup with automatic execution when component unmounts using useEffect
- Function validation with runtime type checking and descriptive error messages
- Stable reference using useRef to maintain current function reference across re-renders
- Memory efficient with proper cleanup to prevent memory leaks and stale closures
- TypeScript support with complete type definitions and parameter validation
- Simple API with single function parameter for ease of use and minimal learning curve
Use Cases
This free open source React hook works well for:
- API request cleanup - Cancel pending network requests built with Next.js and TypeScript
- Timer cleanup - Clear intervals and timeouts using JavaScript patterns
- Event listeners - Remove event listeners and unsubscribe from events with Tailwind CSS apps
- Subscription cleanup - Unsubscribe from WebSocket connections and data streams
- Local storage - Save component state to localStorage before unmounting
- Analytics tracking - Send component usage analytics on unmount
API Reference
useUnmount
Parameter | Type | Description |
---|---|---|
fn | () => void | Required. The cleanup function to run when component unmounts |
Usage Patterns
Basic Cleanup
import { useUnmount } from "@/hooks/use-unmount";
function MyComponent() {
useUnmount(() => {
console.log("Component is unmounting");
});
return <div>Hello world</div>;
}
Timer Cleanup
import { useUnmount } from "@/hooks/use-unmount";
function TimerComponent() {
const timerId = useRef<NodeJS.Timeout>();
useEffect(() => {
timerId.current = setInterval(() => {
console.log("Timer tick");
}, 1000);
}, []);
useUnmount(() => {
if (timerId.current) {
clearInterval(timerId.current);
}
});
return <div>Timer running...</div>;
}
API Request Cleanup
import { useUnmount } from "@/hooks/use-unmount";
function DataComponent() {
const abortController = useRef(new AbortController());
useEffect(() => {
fetch("/api/data", {
signal: abortController.current.signal,
})
.then((response) => response.json())
.then((data) => setData(data))
.catch((error) => {
if (error.name !== "AbortError") {
console.error("Fetch error:", error);
}
});
}, []);
useUnmount(() => {
abortController.current.abort();
});
return <div>Loading data...</div>;
}
Event Listener Cleanup
import { useUnmount } from "@/hooks/use-unmount";
function WindowComponent() {
useEffect(() => {
const handleResize = () => {
console.log("Window resized");
};
window.addEventListener("resize", handleResize);
return () => {
window.removeEventListener("resize", handleResize);
};
}, []);
useUnmount(() => {
console.log("Component unmounted, all listeners cleaned");
});
return <div>Listening to window resize</div>;
}
Implementation Notes
- Hook validates input is a function and throws descriptive error if not
- Uses useRef to maintain stable reference to the latest cleanup function
- Function reference is updated on every render to ensure latest closure is used
- Cleanup function runs only once when component unmounts (useEffect with empty deps)
- Compatible with React 16.8+ and follows all React hooks rules and patterns
- Does not interfere with other useEffect cleanup functions in the same component
- Cleanup function has access to the latest component state and props when called
useToggle
React hook for toggle state management with array return pattern similar to useState. Perfect for React applications requiring clean boolean toggling with Next.js integration and TypeScript support.
useWindowSize
Window dimension tracking with debouncing and SSR support. Perfect for React applications requiring responsive design with Next.js integration and TypeScript support.