@usefy/use-unmount
v0.25.1
Published
A React hook that executes a callback when the component unmounts
Maintainers
Readme
Overview
@usefy/use-unmount runs a callback exactly when a component unmounts. Unlike a raw useEffect cleanup, the callback always sees the latest state and props (closure freshness), errors thrown inside it are caught so they never break the rest of the unmount, and cleanup can be turned on or off with the enabled option — its value is read at unmount time.
Part of the @usefy ecosystem — a collection of production-ready React hooks designed for modern applications.
Why use-unmount?
- Closure Freshness — The callback always sees the latest state/props at unmount time
- Runs Only on Unmount — Toggling
enabledwhile mounted never fires the callback; it fires only on real unmount - Error Handling — Errors thrown in the callback are caught and logged, never breaking the component tree unmount
- TypeScript First — Full type safety with the exported
UseUnmountOptionsinterface - SSR Compatible — Safe to render on the server (Next.js, Remix); the callback never runs during SSR
- Zero Dependencies — Pure React implementation with only a peer dependency on React
Installation
# npm
npm install @usefy/use-unmount
# yarn
yarn add @usefy/use-unmount
# pnpm
pnpm add @usefy/use-unmountPeer Dependencies
This package requires React 18 or 19:
{
"peerDependencies": {
"react": "^18.0.0 || ^19.0.0"
}
}Quick Start
import { useUnmount } from "@usefy/use-unmount";
function MyComponent() {
useUnmount(() => {
console.log("Component unmounted");
});
return <div>Hello</div>;
}API Reference
useUnmount(callback, options?)
Executes callback when the component unmounts. Returns void.
Parameters
| Parameter | Type | Default | Description |
| ---------- | ------------------- | ------- | -------------------------------------------- |
| callback | () => void | — | Function to execute when the component unmounts |
| options | UseUnmountOptions | {} | Optional configuration |
UseUnmountOptions
| Property | Type | Default | Description |
| --------- | --------- | ------- | --------------------------------------------------------------- |
| enabled | boolean | true | Whether to run the callback on unmount, read at unmount time |
Runs only on unmount: the
enabledvalue is captured in a ref and read when the component actually unmounts. Flippingenabledfromtruetofalse(or back) while the component is still mounted never fires the callback.
Examples
Save the latest state on unmount
import { useState } from "react";
import { useUnmount } from "@usefy/use-unmount";
function FormComponent() {
const [formData, setFormData] = useState({});
useUnmount(() => {
// formData holds the latest value at unmount time
saveToLocalStorage(formData);
});
return <form>...</form>;
}Conditional cleanup
import { useUnmount } from "@usefy/use-unmount";
function TrackingComponent({ trackingEnabled }: { trackingEnabled: boolean }) {
useUnmount(
() => {
sendAnalyticsEvent("component_unmounted");
},
{ enabled: trackingEnabled }
);
return <div>Tracked content</div>;
}Resource cleanup
import { useEffect, useRef } from "react";
import { useUnmount } from "@usefy/use-unmount";
function WebSocketComponent() {
const wsRef = useRef<WebSocket | null>(null);
useEffect(() => {
wsRef.current = new WebSocket("wss://example.com");
}, []);
useUnmount(() => {
wsRef.current?.close();
});
return <div>Connected</div>;
}TypeScript
import { useUnmount, type UseUnmountOptions } from "@usefy/use-unmount";
const options: UseUnmountOptions = { enabled: true };
useUnmount(() => {
console.log("Goodbye");
}, options);React StrictMode
In development with React StrictMode, components are intentionally mounted, unmounted, and remounted to detect side effects, so the unmount callback may run more than once during development. This is expected behavior and helps surface non-idempotent cleanup logic.
When to use (and when not to)
Use useUnmount to save data before removal, send exit analytics, clean up resources not managed by useEffect, or take a final state snapshot. Prefer a plain useEffect cleanup for subscriptions, event listeners, and request cancellation — the key difference is that useUnmount guarantees access to the latest values, while useEffect cleanup captures values at effect creation time.
Testing
This package maintains comprehensive test coverage to ensure reliability and stability.
Test Coverage
📊 View Detailed Coverage Report (GitHub Pages)
Test Categories
- Callback execution on unmount
- No callback execution on mount
- No callback execution on rerender
- Callback accesses latest values at unmount time
- Updated callback reference is used on unmount
- Latest state values are captured in callback
- Default enabled state (true)
- Explicit enabled: true and enabled: false
- Callback does not fire while mounted when enabled toggles
- Latest enabled value is honored at unmount time
- Errors in callback are caught and logged
- Unmount process continues despite callback errors
- Non-Error objects thrown are handled
- Independent instances work correctly
- Multiple hooks in same component
- Independent enabled states per instance
- Rapid mount/unmount cycles
- Undefined options handling
- Empty options object
- Null-ish enabled values
- Renders on the server without throwing
- Callback never runs during server rendering
- Async callbacks are executed on unmount
- Async error handling behavior
License
MIT © mirunamu
This package is part of the usefy monorepo.
