Skip to content

Instantly share code, notes, and snippets.

@ibnlanre
Last active September 17, 2023 07:14
Show Gist options
  • Select an option

  • Save ibnlanre/29f681bebb87ede14e2218225302d1d6 to your computer and use it in GitHub Desktop.

Select an option

Save ibnlanre/29f681bebb87ede14e2218225302d1d6 to your computer and use it in GitHub Desktop.
useImageOnLoad hook
import { useImageOnLoad } from "@/hooks";
import { Avatar, Skeleton } from "@mantine/core";
import NextImage from "next/image";
function Component() {
const { markers, markLoad, markError } = useImageOnLoad(
"profile",
"avatar",
"media"
);
return (
<main>
{/* Next Image */}
<Skeleton visible={!markers.profile.complete}>
<NextImage
src="..."
onError={() => markError("profile")}
onLoad={() => markLoad("profile")}
alt="profile picture"
/>
</Skeleton>
{/* JSX Image */}
<Skeleton visible={!markers.media.complete}>
<img
src={markers.media.error ? "/placeholder.jpg" : "..."}
onError={() => markError("media")}
onLoad={() => markLoad("media")}
alt="media house"
/>
</Skeleton>
{/* Mantine Avatar */}
<Skeleton visible={!markers.avatar.complete}>
<Avatar
src="..."
imageProps={{
onError: () => markError("avatar"),
onLoad: () => markLoad("avatar"),
}}
alt="avatar korra" // 🤭
radius="xl"
/>
</Skeleton>
</main>
);
}
import { useReducer } from "react";
type State = {
loaded: boolean;
error: boolean;
complete: boolean;
};
type Markers<T extends string> = Record<T, State>;
type Action<T> = {
key: T;
state: Partial<State>;
};
export function useImageOnLoad<T extends string>(
...markings: ReadonlyArray<T>
) {
const [markers, setMarker] = useReducer(
(prevMarkers: Markers<T>, { key, state }: Action<T>) => ({
...prevMarkers,
[key]: {
...prevMarkers[key],
...state,
},
}),
markings.reduce((markers: Markers<T>, currMarker: T) => {
return {
...markers,
[currMarker]: {
loaded: false,
complete: false,
error: false,
},
};
}, {} as Markers<T>)
);
function markLoad(key: T) {
setMarker({ key, state: { loaded: true, complete: true } });
}
function markError(key: T) {
setMarker({ key, state: { error: true, complete: true } });
}
return {
markers,
markError,
markLoad
};
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment