application-amicale/src/utils/customHooks.tsx
2021-05-13 10:58:47 +02:00

139 lines
3.8 KiB
TypeScript

/*
* Copyright (c) 2019 - 2020 Arnaud Vergnet.
*
* This file is part of Campus INSAT.
*
* Campus INSAT is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Campus INSAT is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Campus INSAT. If not, see <https://www.gnu.org/licenses/>.
*/
import { DependencyList, useEffect, useRef, useState } from 'react';
import { REQUEST_STATUS } from './Requests';
import { ApiRejectType } from './WebData';
export function useMountEffect(func: () => void) {
// eslint-disable-next-line react-hooks/exhaustive-deps
useEffect(func, []);
}
/**
* Effect that does not run on first render
*
* @param effect
* @param deps
*/
export function useSubsequentEffect(effect: () => void, deps?: DependencyList) {
const didMountRef = useRef(false);
useEffect(
() => {
if (didMountRef.current) {
effect();
} else {
didMountRef.current = true;
}
},
// eslint-disable-next-line react-hooks/exhaustive-deps
deps ? deps : []
);
}
export function useRequestLogic<T>(
request: () => Promise<T>,
cache?: T,
onCacheUpdate?: (newCache: T) => void,
startLoading?: boolean,
minRefreshTime?: number
) {
const [response, setResponse] = useState<{
loading: boolean;
lastRefreshDate?: Date;
status: REQUEST_STATUS;
code?: number;
data: T | undefined;
}>({
loading: startLoading !== false && cache === undefined,
lastRefreshDate: undefined,
status: REQUEST_STATUS.SUCCESS,
code: undefined,
data: undefined,
});
const refreshData = (newRequest?: () => Promise<T>) => {
let canRefresh;
if (response.lastRefreshDate && minRefreshTime) {
canRefresh =
new Date().getTime() - response.lastRefreshDate.getTime() >
minRefreshTime;
} else {
canRefresh = true;
}
if (canRefresh) {
if (!response.loading) {
setResponse((prevState) => ({
...prevState,
loading: true,
}));
}
const r = newRequest ? newRequest : request;
r()
.then((requestResponse: T) => {
setResponse({
loading: false,
lastRefreshDate: new Date(),
status: REQUEST_STATUS.SUCCESS,
code: undefined,
data: requestResponse,
});
if (onCacheUpdate) {
onCacheUpdate(requestResponse);
}
})
.catch((error: ApiRejectType | undefined) => {
if (!error) {
setResponse((prevState) => ({
loading: false,
lastRefreshDate: prevState.lastRefreshDate,
status: REQUEST_STATUS.CONNECTION_ERROR,
code: undefined,
data: prevState.data,
}));
} else {
setResponse((prevState) => ({
loading: false,
lastRefreshDate: prevState.lastRefreshDate,
status: error.status,
code: error.code,
data: prevState.data,
}));
}
});
}
};
const value: [
boolean,
Date | undefined,
REQUEST_STATUS,
number | undefined,
T | undefined,
(newRequest?: () => Promise<T>) => void
] = [
response.loading,
response.lastRefreshDate,
response.status,
response.code,
cache ? cache : response.data,
refreshData,
];
return value;
}