Skip to content

Commit 08e0c19

Browse files
committed
fix: 🐛 Clear listeners for generic cache/queue hooks
1 parent 508b751 commit 08e0c19

File tree

5 files changed

+79
-36
lines changed

5 files changed

+79
-36
lines changed

packages/react/__tests__/features/helpers/use-command-events/use-command-events.utils.spec.ts

Lines changed: 0 additions & 31 deletions
This file was deleted.
Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
import { act } from "@testing-library/react";
2+
3+
import { startServer, resetInterceptors, stopServer, createRequestInterceptor } from "../../../server";
4+
import { createRequest, renderUseRequestEvents } from "../../../utils";
5+
6+
describe("useRequestEvents [ Utils ]", () => {
7+
let request = createRequest();
8+
9+
beforeAll(() => {
10+
startServer();
11+
});
12+
13+
afterEach(() => {
14+
resetInterceptors();
15+
});
16+
17+
afterAll(() => {
18+
stopServer();
19+
});
20+
21+
beforeEach(() => {
22+
jest.resetModules();
23+
request = createRequest();
24+
});
25+
26+
describe("When handling lifecycle events", () => {
27+
it("should not throw when removing non existing event", async () => {
28+
const response = renderUseRequestEvents(request);
29+
30+
expect(response.result.current[1].removeLifecycleListener).not.toThrow();
31+
});
32+
it("should unmount lifecycle events when handling requests by queue/cache keys", async () => {
33+
const spy = jest.fn();
34+
createRequestInterceptor(request);
35+
const response = renderUseRequestEvents(request);
36+
37+
await act(async () => {
38+
response.result.current[0].onRequestStart(spy);
39+
response.result.current[1].addLifecycleListeners(request);
40+
response.result.current[1].addLifecycleListeners(request);
41+
response.result.current[1].addLifecycleListeners(request);
42+
43+
await request.send();
44+
});
45+
46+
expect(spy).toBeCalledTimes(1);
47+
});
48+
it("should listen to every request id events", async () => {
49+
const spy = jest.fn();
50+
createRequestInterceptor(request);
51+
const response = renderUseRequestEvents(request);
52+
53+
await act(async () => {
54+
await request.send({
55+
onSettle: (requestId) => {
56+
response.result.current[0].onRequestStart(spy);
57+
response.result.current[1].addLifecycleListeners(request, requestId);
58+
response.result.current[1].addLifecycleListeners(request, requestId);
59+
response.result.current[1].addLifecycleListeners(request, requestId);
60+
},
61+
});
62+
});
63+
64+
expect(spy).toBeCalledTimes(3);
65+
});
66+
});
67+
});

packages/react/src/helpers/use-request-events/use-request-events.hooks.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -175,7 +175,14 @@ export const useRequestEvents = <T extends RequestInstance>({
175175
// ******************
176176

177177
const addLifecycleListeners = (cmd: T, requestId?: string) => {
178+
/**
179+
* useFetch handles requesting by general keys
180+
* This makes it possible to deduplicate requests from different places and share data
181+
*/
178182
if (!requestId) {
183+
// It's important to clear previously attached listeners to not cause some additional response/request
184+
// events to be triggered during lifecycle
185+
clearLifecycleListeners();
179186
const { queueKey, cacheKey } = cmd;
180187
const requestStartUnmount = requestManager.events.onRequestStart(queueKey, handleRequestStart(cmd));
181188
const responseStartUnmount = requestManager.events.onResponseStart(queueKey, handleResponseStart(cmd));
@@ -195,6 +202,9 @@ export const useRequestEvents = <T extends RequestInstance>({
195202

196203
return unmount;
197204
}
205+
/**
206+
* useSubmit handles requesting by requestIds, this makes it possible to track single requests
207+
*/
198208
const requestRemove = requestManager.events.onRemoveById(requestId, handleRemove);
199209
const requestStartUnmount = requestManager.events.onRequestStartById(requestId, handleRequestStart(cmd));
200210
const responseStartUnmount = requestManager.events.onResponseStartById(requestId, handleResponseStart(cmd));

packages/react/src/hooks/use-fetch/use-fetch.hooks.ts

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import { useDebounce, useThrottle } from "@better-hooks/performance";
44
import { RequestInstance, Request, getRequestKey } from "@hyper-fetch/core";
55

66
import { useRequestEvents, useTrackedState } from "helpers";
7-
import { UseFetchOptionsType, useFetchDefaultOptions, UseFetchReturnType, getRefreshTime } from "hooks/use-fetch";
7+
import { UseFetchOptionsType, useFetchDefaultOptions, UseFetchReturnType } from "hooks/use-fetch";
88
import { useConfigProvider } from "config-provider";
99
import { getBounceData } from "utils";
1010
import { InvalidationKeyType } from "types";
@@ -99,9 +99,6 @@ export const useFetch = <RequestType extends RequestInstance>(
9999

100100
function handleRefresh() {
101101
if (!refresh) return;
102-
const time = getRefreshTime(refreshTime, state.timestamp);
103-
104-
logger.debug(`Starting refresh counter, request will be send in ${time}ms`);
105102

106103
refreshDebounce.debounce(() => {
107104
const isBlurred = !appManager.isFocused;
@@ -120,7 +117,7 @@ export const useFetch = <RequestType extends RequestInstance>(
120117

121118
// Start new refresh counter
122119
handleRefresh();
123-
}, time);
120+
});
124121
}
125122

126123
const handleRevalidation = (invalidateKey: InvalidationKeyType) => {

0 commit comments

Comments
 (0)