Skip to content

useEffectAbortable

Custom useEffect with a unified cancellation mechanism to ensure complete cleanup and to prevent the warning that appears on old React version "Can't perform a React state update on an unmounted component".

Demo

INFO

The component has:

  • a state useState variable boolean uaws by a Show component to render the Demo component.
  • a data useState variable with value 0.
  • a button that toggle _state between false and true value.
  • a Demo component that receives the update function for data variable. It has a useEffectAbortable that hat simulates an asynchronous call during which a loading message is shown and at the end of which increment by one date varibale.

If you click the mount button the Demo component is rendering. The simulated call starts and at the end updates the date variable but if the unmount button is clicked before call ending, it will be canceled with the useEffectAbortable and date variable will not be updated.

Loading demo…
Show source code
tsx
import { useState } from "react";
import { useEffectAbortable } from "../../../../hooks";
import { Show } from "../../../..";

const Demo = ({ setDate }: {setDate: (cb: (n:number)=> number) => void}) => {
	const [state, setState] = useState("IDLE");

	useEffectAbortable((signal) => {
		const id = setTimeout(() => {
			setState("LOADING");
		}, 1000);
		const id1 = setTimeout(() => {
			setState("SUCCESS");
			setDate(d => d+1);
		}, 5000)
		signal.addEventListener('abort', () => {
			clearTimeout(id);
			clearTimeout(id1);
		});
	}, []);

	return <p>
		{state}
	</p>

}
const UseEffectAbortable = () => {
	const [state, setState] = useState(false);
	const [data, setData] = useState(0);

	return (<>
		<p>Current state: {state ? "MOUNT" : "UNMOUNT"}</p>
		<p>Current data: {data}</p>
		<button onClick={() => setState(t => !t)}>{state ? "Unmount" : "Mount"}</button>
		<Show when={state}>
			<Demo setDate={setData}/>
		</Show>
	</>);
};

UseEffectAbortable.displayName = "UseEffectAbortable";

export { UseEffectAbortable };

Types

UseEffectAbortableProps

  • @template T - The tuple type of the dependency list. Inferred automatically from the deps argument, providing stricter typing than the standard DependencyList.

Parameters accepted by useEffectAbortable.

PropertyTypeRequiredDescription
cb(signal: AbortSignal) => void \| Promise<void> \| (() => void) \| Promise<() => void>The effect callback, receiving an {@link AbortSignal} that is automatically aborted when the effect is cleaned up (i.e. when deps change or the component unmounts). Supports four return shapes: - void — No cleanup needed; the signal abortion is the only teardown. - Promise&lt;void&gt; — An async effect with no additional cleanup. - () =&gt; void — A synchronous cleanup function, called before the next effect run or on unmount, in addition to aborting the signal. - Promise&lt;() =&gt; void&gt; — An async effect that resolves with a cleanup function, called before the next effect run or on unmount.
depsDependencyListTyped<T>A strictly-typed dependency array (same semantics as useEffect). The effect re-runs and the previous {@link AbortSignal} is aborted whenever any dependency changes. Using {@link DependencyListTyped} instead of the standard DependencyList provides compile-time checking of dependency types.

Released under the MIT License.