blob: 6ae5f7151b102c7f9c12b931b9a71dd18ec4d82b [file] [log] [blame]
idillon18283ac2023-01-07 12:06:42 -05001/*
2 * Copyright (C) 2022 Savoir-faire Linux Inc.
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU Affero General Public License as
6 * published by the Free Software Foundation; either version 3 of the
7 * License, or (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU Affero General Public License for more details.
13 *
14 * You should have received a copy of the GNU Affero General Public
15 * License along with this program. If not, see
16 * <https://www.gnu.org/licenses/>.
17 */
18
19import { QueryKey, useQueryClient } from '@tanstack/react-query';
20import { useCallback } from 'react';
21
22// Test whether two elements are equals or not
23// Return 'true' if they are equal, 'false' otherwise
24export type CheckElementsAreEqual<ElementType> = (element1: ElementType, element2: ElementType) => boolean;
25
26type AddToCacheFn<ElementType> = (element: ElementType) => void;
27
28export const useAddToCache = <ElementType>(
29 queryKey: QueryKey,
30 CheckElementsAreEqual: CheckElementsAreEqual<ElementType>
31): AddToCacheFn<ElementType> => {
32 const queryClient = useQueryClient();
33 return useCallback(
34 (newElement: ElementType) => {
35 // Make sure the element is not already in the cache
36 // This is expected to happen all the time on strict mode
37 const data = queryClient.getQueryData<ElementType[]>(queryKey);
38 if (data?.find((element) => CheckElementsAreEqual(element, newElement))) {
39 return;
40 }
41
42 // Add the element
43 queryClient.setQueryData<ElementType[]>(queryKey, (elements) => [...(elements || []), newElement]);
44 },
45 [CheckElementsAreEqual, queryClient, queryKey]
46 );
47};
48
49// Check whether the passed element is the one we are looking for or not
50type CheckIsElementFn<ElementType, IdentifierType> = (element: ElementType, identifier: IdentifierType) => boolean;
51
52type RemoveFromCacheFn<IdentifierType> = (element: IdentifierType) => void;
53
54export const useRemoveFromCache = <ElementType, IdentifierType>(
55 queryKey: QueryKey,
56 checkIsElementFn: CheckIsElementFn<ElementType, IdentifierType>
57): RemoveFromCacheFn<IdentifierType> => {
58 const queryClient = useQueryClient();
59 return useCallback(
60 (identifier: IdentifierType) => {
61 queryClient.setQueryData<ElementType[]>(queryKey, (elements) =>
62 elements?.filter((element) => !checkIsElementFn(element, identifier))
63 );
64 },
65 [checkIsElementFn, queryClient, queryKey]
66 );
67};