mirror of
https://github.com/aliasvault/aliasvault.git
synced 2026-03-20 23:52:31 -04:00
59 lines
1.8 KiB
TypeScript
59 lines
1.8 KiB
TypeScript
import { useState, useEffect, useCallback, useRef } from 'react';
|
|
|
|
/**
|
|
* Hook that ensures a loading state persists for a minimum duration before being set to false.
|
|
* This improves the user experience by preventing the loading state from flickering.
|
|
*
|
|
* @param initialState - Initial loading state
|
|
* @param minDuration - Minimum duration in milliseconds
|
|
* @returns [isLoading, setIsLoading] - Loading state and setter
|
|
*/
|
|
export const useMinDurationLoading = (
|
|
initialState: boolean = false,
|
|
minDuration: number = 300
|
|
): [boolean, (value: boolean) => void] => {
|
|
const [isLoading, setIsLoading] = useState(initialState);
|
|
const timeoutRef = useRef<NodeJS.Timeout | null>(null);
|
|
const startTimeRef = useRef<number | null>(null);
|
|
|
|
const setLoadingState = useCallback((value: boolean) => {
|
|
if (value) {
|
|
// Starting to load
|
|
setIsLoading(true);
|
|
startTimeRef.current = Date.now();
|
|
} else {
|
|
// Finishing loading - ensure minimum duration
|
|
const elapsedTime = startTimeRef.current ? Date.now() - startTimeRef.current : 0;
|
|
const remainingTime = Math.max(0, minDuration - elapsedTime);
|
|
|
|
if (remainingTime === 0) {
|
|
setIsLoading(false);
|
|
} else {
|
|
if (timeoutRef.current) {
|
|
clearTimeout(timeoutRef.current);
|
|
}
|
|
timeoutRef.current = setTimeout(() => {
|
|
setIsLoading(false);
|
|
}, remainingTime);
|
|
}
|
|
}
|
|
}, [minDuration]);
|
|
|
|
// Handle initial loading state only once
|
|
useEffect(() => {
|
|
if (initialState) {
|
|
setIsLoading(true);
|
|
startTimeRef.current = Date.now();
|
|
}
|
|
}, [initialState, setIsLoading]);
|
|
|
|
useEffect(() => {
|
|
return (): void => {
|
|
if (timeoutRef.current) {
|
|
clearTimeout(timeoutRef.current);
|
|
}
|
|
};
|
|
}, []);
|
|
|
|
return [isLoading, setLoadingState];
|
|
}; |