@samitouri / QOSami-HFS / commits / b6cc92a7

fix: plugin/list-uploader: working only on first item

Massimo Melina committed Sep 18, 2023 at 14:25 UTC b6cc92a7c41a9a132366ee4d237b8e188224b075
1 file changed +22 -16
shared/react.ts
+22 -16
@@ -41,6 +41,11 @@ export function dontBotherWithKeys(elements: ReactNode[]): (ReactNode|string)[]
41 : h(Fragment, { key:i, children:e }) )
42 }
43
44 +export function useRequestRender() {
45 + const [state, setState] = useState(0)
46 + return Object.assign(useCallback(() => setState(x => x + 1), [setState]), { state })
47 +}
48 +
49 /* the idea is that you need a job done by a worker, but the worker will execute only after it collected jobs for some time
50 by other "users" of the same worker, like other instances of the same component, but potentially also different components.
51 User of this hook will just be returned with the single result of its own job.
@@ -52,29 +57,30 @@ export function useBatch<Job=unknown,Result=unknown>(
57 { delay=0 }={}
58 ) {
59 interface Env {
55 - batch: Set<Job>,
56 - cache: Map<Job, Result | null>,
57 - timeout?: ReturnType<typeof setTimeout>
60 + batch: Set<Job>
61 + cache: Map<Job, Result | null>
62 + waiter: Promise<void>
63 }
64 const worker2env = (useBatch as any).worker2env ||= worker && new Map<typeof worker, Env>()
60 - const env = worker && (worker2env.get(worker) || (() => {
65 + const env = (worker2env.get(worker) || (() => {
66 const ret = { batch: new Set<Job>(), cache: new Map<Job, Result>() } as Env
67 worker2env.set(worker, ret)
68 return ret
69 })())
65 - const [, setRefresher] = useState(0)
70 + const requestRender = useRequestRender()
71 useEffect(() => {
67 - if (!env) return
68 - env.timeout ||= setTimeout(async () => {
69 - env.timeout = undefined
70 - const jobs = [...env.batch.values()]
71 - env.batch.clear()
72 - const res = await worker(jobs)
73 - let i = 0
74 - for (const job of jobs)
75 - env.cache.set(job, res[i++] ?? null)
76 - setRefresher(x => x + 1)
77 - }, delay)
72 + (env.waiter ||= new Promise<void>(resolve => {
73 + setTimeout(async () => {
74 + env.timeout = undefined
75 + const jobs = [...env.batch.values()]
76 + env.batch.clear()
77 + const res = await worker(jobs)
78 + let i = 0
79 + for (const job of jobs)
80 + env.cache.set(job, res[i++] ?? null)
81 + resolve()
82 + }, delay)
83 + })).then(requestRender)
84 }, [])
85 const cached = env?.cache.get(job)
86 if (env && cached === undefined)