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)