npm.io
2.1.2 • Published 3d ago

use-is-mounted-ref

Licence
MIT
Version
2.1.2
Deps
0
Vulns
0
Weekly
0
Stars
44

use-is-mounted-ref

React hooks that cancel async work when a component unmounts.

build version MIT License downloads


Why

Work started from an event handler outlives the component. A request, listener or timer keeps running after unmount and can update stale state.

These hooks give you an AbortSignal tied to the component's lifetime. They are safe under React Strict Mode.

Install

npm install use-is-mounted-ref

Requires React 16.8 or later. CI tests React 18 and 19.

Quick start

import { useAbortSignal } from 'use-is-mounted-ref';

function SaveButton({ data }) {
  const signal = useAbortSignal();

  const save = () =>
    fetch('/api/save', { method: 'POST', body: JSON.stringify(data), signal }).catch((err) => {
      if (err.name !== 'AbortError') throw err;
    });

  return <button onClick={save}>Save</button>;
}

If the component unmounts mid-request, the request is aborted.

API

Hook Returns Aborts / flips when
useAbortSignal() AbortSignal Component unmounts
useAbortController() AbortController Component unmounts
useIsMountedRef() { readonly current: boolean } Component unmounts

All three return a stable value across renders.

useAbortSignal

Use it when you only need the signal. This covers most cases.

useAbortController

Use it when you also need to call abort() yourself, for example from a Cancel button.

Example: cancel button
import { useAbortController } from 'use-is-mounted-ref';

function Upload({ file }) {
  const controller = useAbortController();

  const upload = () => fetch('/api/upload', { method: 'POST', body: file, signal: controller.signal });

  return (
    <>
      <button onClick={upload}>Upload</button>
      <button onClick={() => controller.abort()}>Cancel</button>
    </>
  );
}

Once aborted, the controller stays aborted until the component remounts.

useIsMountedRef

Use it for promises that cannot take a signal, such as some third-party SDKs.

Example: guard a non-abortable promise
import { useState } from 'react';
import { useIsMountedRef } from 'use-is-mounted-ref';

function Profile({ sdk }) {
  const isMountedRef = useIsMountedRef();
  const [user, setUser] = useState(null);

  const load = async () => {
    const result = await sdk.getUser();
    if (isMountedRef.current) setUser(result);
  };

  return <button onClick={load}>{user ? user.name : 'Load'}</button>;
}

Inside useEffect

These hooks abort only on unmount, not when effect dependencies change. For work keyed on props, create a controller per effect run:

useEffect(() => {
  const controller = new AbortController();
  fetch(`/api/users/${id}`, { signal: controller.signal });
  return () => controller.abort();
}, [id]);

Docs

Contributing

See CONTRIBUTING.md. Report bugs or suggest ideas in issues.

License

MIT License helderberto

Keywords