Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- import { useState, useCallback } from 'react';
- import useGetCurrentValue from 'Hooks/Common/useGetCurrentValue';
- type TRemoteValidator<TArgs extends any[]> = (...args: TArgs) => Promise<boolean>;
- const isDelayPending = (lastRequest: number, delay: number) => Date.now() - lastRequest < delay;
- const wasRequestCanceled = (currentRequest: number, lastRequest: number) => currentRequest !== lastRequest;
- const neverResolvedPromise = () => new Promise<boolean>((resolve) => { });
- const useRemoteValidation = <TArgs extends any[]>(
- remoteValidator: TRemoteValidator<TArgs>,
- delay: number = 0,
- ) => {
- const [isLoading, setIsLoading] = useState(false);
- const [lastRequest, setLastRequest] = useState(0);
- const remoteValidatorRef = useGetCurrentValue(remoteValidator);
- const lastRequestRef = useGetCurrentValue(lastRequest);
- const validate = useCallback<TRemoteValidator<TArgs>>(
- (...args: TArgs) => {
- const currentRequest = Date.now();
- setLastRequest(currentRequest);
- setIsLoading(true);
- const currentRemoteValidatorPromise = () => remoteValidatorRef()(...args)
- .then((response) => response)
- .catch((error) => error)
- .then((result) => {
- if (wasRequestCanceled(currentRequest, lastRequestRef())) {
- return neverResolvedPromise();
- }
- setIsLoading(false);
- // this means that error occured, return is valid
- if (typeof result !== 'boolean') {
- console.log('Validation failed.', result);
- return true;
- }
- return result;
- });
- return new Promise<boolean>((resolve) => {
- const timeoutCallback = () => {
- if (isDelayPending(lastRequestRef(), delay)) {
- return;
- }
- resolve(currentRemoteValidatorPromise());
- };
- setTimeout(timeoutCallback, delay);
- });
- },
- [
- delay,
- lastRequestRef,
- setLastRequest,
- setIsLoading,
- remoteValidatorRef,
- ]
- );
- return {
- isLoading,
- validate,
- };
- };
- export default useRemoteValidation;
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement