Skip to content

Instantly share code, notes, and snippets.

@crisu83
Last active December 4, 2020 15:30
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save crisu83/36fc4a760e8d1d9a783c268f33d1b42f to your computer and use it in GitHub Desktop.
Save crisu83/36fc4a760e8d1d9a783c268f33d1b42f to your computer and use it in GitHub Desktop.
React loader implementation
import React from 'react';
export default function LoaderExample() {
comst {data, loading, error} = useMyQuery(); // Implementation specific
const {Loader, data: myData} = useLoader({
data,
errorMessage: error?.message,
isLoading: loading,
});
return (
<Loader>
{myData && JSON.stringify(myData)}
</Loader>
);
}
import {Text} from '@/design-system';
import React, {PropsWithChildren, useEffect, useState} from 'react';
import Center from './center';
import Spinner from './spinner';
function Loading() {
return (
<Center>
<Spinner width={100} />
</Center>
);
}
type ErrorProps = {
errorMessage: string;
};
function Error({errorMessage}: ErrorProps) {
return (
<Center>
<Text color="mediumContrast" fontSize={4} fontWeight="bold">
{errorMessage}
</Text>
</Center>
);
}
type LoaderConfig<T> = {
data: T;
delay?: number;
errorMessage?: string;
isLoading: boolean;
};
export function useLoader<T>({
data,
delay = 800,
errorMessage,
isLoading,
}: LoaderConfig<T>) {
return {
Loader({children}: PropsWithChildren<{}>) {
const [isDone, setIsDone] = useState(false);
useEffect(() => {
const timer = setTimeout(() => {
setIsDone(true);
}, delay);
return () => clearTimeout(timer);
}, []);
if (isLoading || !isDone) {
return <Loading />;
}
if (errorMessage) {
return <Error errorMessage={errorMessage} />;
}
return <>{children}</>;
},
data,
};
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment