Skip to content

Commit 0b64c9a

Browse files
committed
fix single query case
1 parent b89904c commit 0b64c9a

3 files changed

Lines changed: 46 additions & 77 deletions

File tree

frontend/__tests__/components/common/AsyncContent.spec.tsx

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -381,14 +381,17 @@ describe("AsyncContent", () => {
381381
{...(options as Props<Q>)}
382382
alwaysShowContent
383383
>
384-
{({ first, second }) => (
384+
{(data) => (
385385
<>
386386
<Show
387-
when={first() !== undefined && second() !== undefined}
387+
when={
388+
data()?.first !== undefined &&
389+
data()?.second !== undefined
390+
}
388391
fallback={<div>no data</div>}
389392
>
390-
<div data-testid="first">{first()}</div>
391-
<div data-testid="second">{second()}</div>
393+
<div data-testid="first">{data()?.first}</div>
394+
<div data-testid="second">{data()?.second}</div>
392395
</Show>
393396
</>
394397
)}
@@ -402,14 +405,16 @@ describe("AsyncContent", () => {
402405
{...(options as Props<Q>)}
403406
alwaysShowContent={false}
404407
>
405-
{({ first, second }) => (
408+
{(data) => (
406409
<>
407410
<Show
408-
when={first() !== undefined && second() !== undefined}
411+
when={
412+
data().first !== undefined && data().second !== undefined
413+
}
409414
fallback={<div>no data</div>}
410415
>
411-
<div data-testid="first">{first()}</div>
412-
<div data-testid="second">{second()}</div>
416+
<div data-testid="first">{data().first}</div>
417+
<div data-testid="second">{data().second}</div>
413418
</Show>
414419
</>
415420
)}

frontend/src/ts/components/common/AsyncContent.tsx

Lines changed: 8 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -54,8 +54,6 @@ type SingleCollectionProps<T> = {
5454
collection: Collection<T>;
5555
};
5656

57-
type AccessorMap<T> = { [K in keyof T]: Accessor<T[K]> };
58-
5957
type DeferredChildren<T extends QueryMapping> = {
6058
alwaysShowContent?: false;
6159
children: (data: Accessor<{ [K in keyof T]: T[K] }>) => JSXElement;
@@ -69,37 +67,23 @@ type EagerChildren<T extends QueryMapping> = {
6967
) => JSXElement;
7068
};
7169

72-
type MultiDeferredChildren<T extends QueryMapping> = {
73-
alwaysShowContent?: false;
74-
children: (data: AccessorMap<{ [K in keyof T]: T[K] }>) => JSXElement;
75-
};
76-
77-
type MultiEagerChildren<T extends QueryMapping> = {
78-
alwaysShowContent: true;
79-
showLoader?: true;
80-
children: (
81-
data: AccessorMap<{ [K in keyof T]: T[K] | undefined }>,
82-
) => JSXElement;
83-
};
84-
8570
type SingleSource<T> = SingleQueryProps<T> | SingleCollectionProps<T>;
8671
type MultiSource<T extends QueryMapping> = QueryProps<T> | CollectionProps<T>;
87-
type SingleChildren<T> = DeferredChildren<T> | EagerChildren<T>;
88-
type MultiChildren<T extends QueryMapping> =
89-
| MultiDeferredChildren<T>
90-
| MultiEagerChildren<T>;
72+
type ChildrenProps<T extends QueryMapping> =
73+
| DeferredChildren<T>
74+
| EagerChildren<T>;
9175

9276
export type Props<T extends QueryMapping> = BaseProps &
9377
(SingleSource<T> | MultiSource<T>) &
94-
(SingleChildren<T> | MultiChildren<T>);
78+
ChildrenProps<T>;
9579

9680
// Single query/collection overloads
9781
function AsyncContent<T>(
98-
props: BaseProps & SingleSource<T> & SingleChildren<T>,
82+
props: BaseProps & SingleSource<T> & ChildrenProps<T>,
9983
): JSXElement;
10084
// Multi query/collection overloads
10185
function AsyncContent<T extends Record<string, unknown>>(
102-
props: BaseProps & MultiSource<T> & MultiChildren<T>,
86+
props: BaseProps & MultiSource<T> & ChildrenProps<T>,
10387
): JSXElement;
10488
function AsyncContent<T extends QueryMapping>(props: Props<T>): JSXElement {
10589
//@ts-expect-error this is fine
@@ -173,27 +157,6 @@ function AsyncContent<T extends QueryMapping>(props: Props<T>): JSXElement {
173157
false,
174158
);
175159

176-
// Keys are stable for the component lifetime; per-key closures track
177-
// reactivity internally via value()/lastResolvedValue().
178-
// oxlint-disable solid/reactivity
179-
const multi = !("defaultQuery" in source());
180-
181-
const eagerAccessorMap = multi
182-
? (Object.fromEntries(
183-
typedKeys(source()).map((key) => [key, () => value()?.[key]]),
184-
) as AccessorMap<{ [K in keyof T]: T[K] | undefined }>)
185-
: undefined;
186-
187-
const deferredAccessorMap = multi
188-
? (Object.fromEntries(
189-
typedKeys(source()).map((key) => [
190-
key,
191-
() => lastResolvedValue()?.[key],
192-
]),
193-
) as AccessorMap<{ [K in keyof T]: T[K] }>)
194-
: undefined;
195-
// oxlint-enable solid/reactivity
196-
197160
const loader = (): JSXElement =>
198161
props.loader ?? <LoadingCircle class="p-4 text-center text-2xl" />;
199162

@@ -221,16 +184,14 @@ function AsyncContent<T extends QueryMapping>(props: Props<T>): JSXElement {
221184
{(_) =>
222185
// oxlint-disable-next-line typescript/no-explicit-any
223186
(props.children as (data: any) => JSXElement)(
224-
multi ? deferredAccessorMap : lastResolvedValue,
187+
lastResolvedValue,
225188
)
226189
}
227190
</Show>
228191
}
229192
>
230193
{/* oxlint-disable-next-line typescript/no-explicit-any */}
231-
{(props.children as (data: any) => JSXElement)(
232-
multi ? eagerAccessorMap : value,
233-
)}
194+
{(props.children as (data: any) => JSXElement)(value)}
234195
</Show>
235196
</>
236197
}

frontend/src/ts/components/pages/leaderboard/LeaderboardPage.tsx

Lines changed: 25 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -203,28 +203,31 @@ export function LeaderboardPage(): JSXElement {
203203
alwaysShowContent
204204
errorClass="rounded bg-sub-alt p-4"
205205
>
206-
{({ data, rank, config }) => (
207-
<UserRank
208-
type={getSelection().type === "weekly" ? "xp" : "speed"}
209-
data={rank()}
210-
friendsOnly={getSelection().friendsOnly}
211-
total={data()?.count}
212-
minWpm={(() => {
213-
const d = data();
214-
return d && "minWpm" in d
215-
? (d.minWpm as number)
216-
: undefined;
217-
})()}
218-
memoryDifference={getLbMemoryDifference(
219-
getSelection(),
220-
rank()?.rank,
221-
)}
222-
isLbOptOut={getSnapshot()?.lbOptOut ?? false}
223-
isBanned={getSnapshot()?.banned ?? false}
224-
minTimeTyping={config()?.leaderboards.minTimeTyping ?? 0}
225-
userTimeTyping={getSnapshot()?.typingStats.timeTyping ?? 0}
226-
/>
227-
)}
206+
{(results) => {
207+
const r = results();
208+
return (
209+
<UserRank
210+
type={getSelection().type === "weekly" ? "xp" : "speed"}
211+
data={r?.rank}
212+
friendsOnly={getSelection().friendsOnly}
213+
total={r?.data?.count}
214+
minWpm={(() => {
215+
const d = r?.data;
216+
return d && "minWpm" in d
217+
? (d.minWpm as number)
218+
: undefined;
219+
})()}
220+
memoryDifference={getLbMemoryDifference(
221+
getSelection(),
222+
r?.rank?.rank,
223+
)}
224+
isLbOptOut={getSnapshot()?.lbOptOut ?? false}
225+
isBanned={getSnapshot()?.banned ?? false}
226+
minTimeTyping={r?.config?.leaderboards.minTimeTyping ?? 0}
227+
userTimeTyping={getSnapshot()?.typingStats.timeTyping ?? 0}
228+
/>
229+
);
230+
}}
228231
</AsyncContent>
229232
</Show>
230233

0 commit comments

Comments
 (0)