Skip to content

Instantly share code, notes, and snippets.

@DennisSmolek
Last active September 18, 2024 09:34
Show Gist options
  • Select an option

  • Save DennisSmolek/e19c01f9f2dc1ed02fe3d1ae368daedc to your computer and use it in GitHub Desktop.

Select an option

Save DennisSmolek/e19c01f9f2dc1ed02fe3d1ae368daedc to your computer and use it in GitHub Desktop.
Adds event notification for the suspense with a little delay
// This creates a wrapper around suspense to notify when the transition takes place
import {
Suspense as ReactSuspense,
useState,
useEffect,
useCallback,
useMemo,
useRef,
} from "react";
interface SuspenseProps {
children: React.ReactNode;
onChange?: (status: boolean) => void;
onRender?: () => void;
onFallback?: () => void;
fallback?: React.ReactNode;
delay?: number;
}
export const Suspense: React.FC<SuspenseProps> = ({
children,
onChange,
onRender,
onFallback,
fallback,
delay,
}) => {
const [isLoaded, setIsLoaded] = useState(false);
const oldIsLoaded = useRef(false);
//const initTime = useMemo(() => performance.now(), []);
const timeoutHolder = useRef(null);
// handle all possible props to notify
const notifyChange = useCallback(
(status: boolean) => {
if (onChange) onChange(status);
if (onRender && status) onRender();
if (onFallback && !status) onFallback();
},
[onChange, onRender, onFallback]
);
// fire the changes
useEffect(() => {
if (oldIsLoaded.current === isLoaded) return;
oldIsLoaded.current = isLoaded;
// we are going to throttle changes to state
if (timeoutHolder.current) clearTimeout(timeoutHolder.current);
timeoutHolder.current = setTimeout(() => {
notifyChange(isLoaded);
}, delay || 200);
}, [notifyChange, isLoaded, delay]);
return (
<ReactSuspense
fallback={
<OnRender
fallback={fallback}
onRender={() => setIsLoaded(false)}
/>
}>
{children}
<OnRender onRender={() => setIsLoaded(true)} />
</ReactSuspense>
);
};
interface OnRenderProps {
onRender: () => void;
fallback?: React.ReactNode;
}
const OnRender: React.FC<OnRenderProps> = ({ onRender, fallback }) => {
useEffect(() => onRender(), [onRender]);
return fallback;
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment