diff --git a/src/use-unmount/README.md b/src/use-unmount/README.md new file mode 100644 index 0000000..03ba309 --- /dev/null +++ b/src/use-unmount/README.md @@ -0,0 +1,27 @@ +## 🪝 useUnmount + +```ts +function useUnmount(callback: () => void): void; +``` + +Calls the callback when the component unmounts. This is useful for cleaning up side effects. + +### 📕 Parameters + +- `callback` - The callback to call when the component unmounts. + +### 📗 Returns + +- `void` + +### 📘 Example + +```tsx +export default function Component() { + useUnmount(() => { + print("Unmounting..."); + }); + + return ; +} +``` diff --git a/src/use-unmount/index.ts b/src/use-unmount/index.ts new file mode 100644 index 0000000..7f75147 --- /dev/null +++ b/src/use-unmount/index.ts @@ -0,0 +1 @@ +export * from "./use-unmount"; diff --git a/src/use-unmount/use-unmount.spec.ts b/src/use-unmount/use-unmount.spec.ts new file mode 100644 index 0000000..8ee21ac --- /dev/null +++ b/src/use-unmount/use-unmount.spec.ts @@ -0,0 +1,32 @@ +/// + +import { renderHook } from "../utils/testez"; +import { useUnmount } from "./use-unmount"; + +export = () => { + it("should call when component unmounts", () => { + let called = false; + const { unmount } = renderHook(() => useUnmount(() => (called = true))); + expect(called).to.equal(false); + unmount(); + expect(called).to.equal(true); + }); + + it("should not call on rerender", () => { + let called = false; + const { rerender } = renderHook(() => useUnmount(() => (called = true))); + expect(called).to.equal(false); + rerender(); + expect(called).to.equal(false); + }); + + it("should call the last callback on unmount", () => { + let called = 0; + const { rerender, unmount } = renderHook((callback: () => void) => useUnmount(callback), { + initialProps: () => (called = 0), + }); + rerender(() => (called += 1)); + unmount(); + expect(called).to.equal(1); + }); +}; diff --git a/src/use-unmount/use-unmount.ts b/src/use-unmount/use-unmount.ts new file mode 100644 index 0000000..f306783 --- /dev/null +++ b/src/use-unmount/use-unmount.ts @@ -0,0 +1,16 @@ +import { useEffect } from "@rbxts/roact-hooked"; +import { useLatest } from "../use-latest"; + +/** + * Calls the callback when the component unmounts. + * @param callback The callback to call. + */ +export function useUnmount(callback: () => void) { + const callbackRef = useLatest(callback); + + useEffect(() => { + return () => { + callbackRef.current(); + }; + }, []); +}