@ehsaneha/react-throttle
Version:
useThrottle is a custom React hook that limits how often a function can be called by ensuring it's invoked at most once within a specified delay period.
55 lines (54 loc) • 2.48 kB
JavaScript
import React, { useState } from "react";
import { render, fireEvent, screen, act } from "@testing-library/react";
import { useThrottle } from "./index";
jest.useFakeTimers();
function TestComponent({ delay = 1000 }) {
const [value, setValue] = useState("");
const throttledFn = useThrottle((newVal) => {
setValue(newVal);
}, delay);
return (React.createElement("div", null,
React.createElement("button", { onClick: () => throttledFn("A") }, "Click A"),
React.createElement("button", { onClick: () => throttledFn("B") }, "Click B"),
React.createElement("div", { "data-testid": "output" }, value)));
}
describe("useThrottle (with test component)", () => {
it("calls throttled function immediately on first call", () => {
render(React.createElement(TestComponent, null));
fireEvent.click(screen.getByText("Click A"));
expect(screen.getByTestId("output").textContent).toBe("A");
});
it("throttles multiple rapid calls", () => {
render(React.createElement(TestComponent, null));
fireEvent.click(screen.getByText("Click A"));
fireEvent.click(screen.getByText("Click B")); // Should be throttled
expect(screen.getByTestId("output").textContent).toBe("A");
act(() => {
jest.advanceTimersByTime(1000);
});
expect(screen.getByTestId("output").textContent).toBe("B");
});
it("does not call throttled function again until delay passes", () => {
render(React.createElement(TestComponent, { delay: 500 }));
fireEvent.click(screen.getByText("Click A"));
act(() => {
jest.advanceTimersByTime(300);
});
fireEvent.click(screen.getByText("Click B")); // Should still be throttled
expect(screen.getByTestId("output").textContent).toBe("A");
act(() => {
jest.advanceTimersByTime(300);
});
expect(screen.getByTestId("output").textContent).toBe("B");
});
it("cleans up on unmount without calling throttled function again", () => {
const { unmount } = render(React.createElement(TestComponent, null));
fireEvent.click(screen.getByText("Click A"));
fireEvent.click(screen.getByText("Click B"));
unmount();
act(() => {
jest.runAllTimers();
});
// Can't assert directly, but this ensures no error is thrown
});
});