useAsyncDisposable
Manages async disposable resources using the TC39 Explicit Resource Management proposal.
About
Bridges TC39 Explicit Resource Management (Symbol.asyncDispose) with React lifecycles. It asynchronously creates a disposable resource and disposes it when the component unmounts or when the dependency array changes.
This hook requires Symbol.asyncDispose support at runtime. Browsers such as Safari currently need a polyfill. Load one like core-js/proposals/explicit-resource-management before using this hook.
Examples
Basic usage
import { useAsyncDisposable } from "rooks/experimental";
class ManagedConnection {
async [Symbol.asyncDispose]() {
// close the resource
}
}
async function openConnection() {
return new ManagedConnection();
}
function Screen() {
const connection = useAsyncDisposable(() => openConnection(), []);
if (connection === null) {
return <div>Loading...</div>;
}
return <div>Ready</div>;
}Recreate the resource when dependencies change
import { useState } from "react";
import { useAsyncDisposable } from "rooks/experimental";
class UserScopedConnection {
constructor(public userId: string) {}
async [Symbol.asyncDispose]() {
// close the user-specific resource
}
}
async function openUserConnection(userId: string) {
return new UserScopedConnection(userId);
}
function UserConnectionPanel() {
const [userId, setUserId] = useState("alice");
const resource = useAsyncDisposable(
() => openUserConnection(userId),
[userId]
);
return (
<div>
<button onClick={() => setUserId("bob")}>Switch user</button>
<div>{resource ? `Connected as ${resource.userId}` : "Loading..."}</div>
</div>
);
}Parameters
| Argument | Type | Description | Default value |
|---|---|---|---|
factory | () => Promise<T> | Async function that creates the resource | required |
deps | DependencyList | Dependency array controlling when the resource is replaced | [] |
Return value
| Return value | Type | Description |
|---|---|---|
resource | T | null | The resource, or null while the factory is still resolving |
Notes
- Import from
rooks/experimental, notrooks. rooksdoes not polyfillSymbol.asyncDisposefor you.- If deps change before the factory resolves, the stale resource is disposed immediately when it arrives.
Behavior and lifecycle
The factory starts from an effect and the hook returns null until it resolves. A dependency change or unmount clears the published resource and invokes [Symbol.asyncDispose]() without blocking React cleanup. If an obsolete factory resolves later, its resource is disposed immediately instead of being published. Development Strict Mode can create and dispose more than once, so both operations must be safe to repeat.
Compatibility and accessibility
SSR returns null because the factory runs only on the client. Missing Symbol.asyncDispose support throws from the effect. Factory rejections are not converted into hook state, and asynchronous disposal failures are intentionally ignored; handle or report failures inside those functions. Load the polyfill before React mounts when the runtime lacks the symbol.