Created
March 6, 2024 02:58
-
-
Save jeremy-code/42255192c2268dcbab83f8a37ed34258 to your computer and use it in GitHub Desktop.
useProgressStore hook, get progress from a ky event handler
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// when you create ky instance, set onDownloadProgress: progressStore.setSnapshot, | |
import { useSyncExternalStore } from "react"; | |
import type { DownloadProgress } from "ky"; | |
export const shallowCompare = <T extends Record<string, unknown>>(obj1: T, obj2: T) => { | |
if (Object.is(obj1, obj2)) return true; | |
if (!(obj1 instanceof Object) || !(obj2 instanceof Object)) return false; | |
const entries1 = Object.entries(obj1); | |
const entries2 = Object.entries(obj2); | |
return ( | |
entries1.length === entries2.length && !entries1.some(([key, value]) => obj2[key] !== value) | |
); | |
}; | |
const createProgressStore = () => { | |
const subscribers = new Set<() => void>(); | |
let progress: DownloadProgress = { percent: 0, transferredBytes: 0, totalBytes: 0 }; | |
const subscribe = (subscriber: () => void) => { | |
subscribers.add(subscriber); | |
return () => { | |
subscribers.delete(subscriber); | |
}; | |
}; | |
const getProgress = () => progress; | |
const setProgress = (newProgress: DownloadProgress) => { | |
// Since `useSyncExternalStore` will re-render the component if the snapshot changes through `Object.is` | |
// comparison, the object (and thus, reference) is only updated if any of the properties have changed. | |
if (!shallowCompare(progress, newProgress)) { | |
progress = newProgress; | |
} | |
subscribers.forEach((subscriber) => subscriber()); | |
}; | |
return { subscribe, getSnapshot: getProgress, setSnapshot: setProgress }; | |
}; | |
export const progressStore = createProgressStore(); | |
export const useProgressStore = () => | |
useSyncExternalStore(progressStore.subscribe, progressStore.getSnapshot); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment