You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
49 lines
1.1 KiB
49 lines
1.1 KiB
4 years ago
|
import * as React from 'react';
|
||
|
|
||
|
/**
|
||
|
* Always debounce error to avoid [error -> null -> error] blink
|
||
|
*/
|
||
|
export default function useCacheErrors(
|
||
|
errors: React.ReactNode[],
|
||
|
changeTrigger: (visible: boolean) => void,
|
||
|
directly: boolean,
|
||
|
): [boolean, React.ReactNode[]] {
|
||
|
const cacheRef = React.useRef({
|
||
|
errors,
|
||
|
visible: !!errors.length,
|
||
|
});
|
||
|
|
||
|
const [, forceUpdate] = React.useState({});
|
||
|
|
||
|
const update = () => {
|
||
|
const prevVisible = cacheRef.current.visible;
|
||
|
const newVisible = !!errors.length;
|
||
|
|
||
|
const prevErrors = cacheRef.current.errors;
|
||
|
cacheRef.current.errors = errors;
|
||
|
cacheRef.current.visible = newVisible;
|
||
|
|
||
|
if (prevVisible !== newVisible) {
|
||
|
changeTrigger(newVisible);
|
||
|
} else if (
|
||
|
prevErrors.length !== errors.length ||
|
||
|
prevErrors.some((prevErr, index) => prevErr !== errors[index])
|
||
|
) {
|
||
|
forceUpdate({});
|
||
|
}
|
||
|
};
|
||
|
|
||
|
React.useEffect(() => {
|
||
|
if (!directly) {
|
||
|
const timeout = setTimeout(update, 10);
|
||
|
return () => clearTimeout(timeout);
|
||
|
}
|
||
|
}, [errors]);
|
||
|
|
||
|
if (directly) {
|
||
|
update();
|
||
|
}
|
||
|
|
||
|
return [cacheRef.current.visible, cacheRef.current.errors];
|
||
|
}
|