Skip to content

Commit 1478042

Browse files
committed
perf: converts org list from For to Index to avoid DOM recreation
1 parent e932648 commit 1478042

File tree

1 file changed

+16
-16
lines changed

1 file changed

+16
-16
lines changed

src/app/components/onboarding/RepoSelector.tsx

Lines changed: 16 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@ import {
22
createSignal,
33
createEffect,
44
createMemo,
5-
For,
65
Show,
76
Index,
87
} from "solid-js";
@@ -290,23 +289,24 @@ export default function RepoSelector(props: RepoSelectorProps) {
290289
</div>
291290
</Show>
292291

293-
{/* Per-org repo lists */}
294-
<For each={sortedOrgStates()}>
292+
{/* Per-org repo lists — Index (not For) avoids tearing down every org's
293+
DOM subtree when a single org's state updates via setOrgStates(prev.map(...)) */}
294+
<Index each={sortedOrgStates()}>
295295
{(state) => {
296-
const visible = createMemo(() => filteredReposForOrg(state));
296+
const visible = createMemo(() => filteredReposForOrg(state()));
297297

298298
return (
299299
<div class="overflow-hidden rounded-lg border border-gray-200 dark:border-gray-700">
300300
{/* Org header */}
301301
<div class="flex items-center justify-between border-b border-gray-200 bg-gray-50 px-4 py-2 dark:border-gray-700 dark:bg-gray-800/60">
302302
<span class="text-sm font-semibold text-gray-800 dark:text-gray-200">
303-
{state.org}
303+
{state().org}
304304
</span>
305-
<Show when={!state.loading && !state.error}>
305+
<Show when={!state().loading && !state().error}>
306306
<div class="flex gap-2">
307307
<button
308308
type="button"
309-
onClick={() => selectAllInOrg(state)}
309+
onClick={() => selectAllInOrg(state())}
310310
disabled={
311311
visible().length === 0 ||
312312
visible().every((r) => isSelected(r.fullName))
@@ -318,7 +318,7 @@ export default function RepoSelector(props: RepoSelectorProps) {
318318
<span class="text-gray-300 dark:text-gray-600">·</span>
319319
<button
320320
type="button"
321-
onClick={() => deselectAllInOrg(state)}
321+
onClick={() => deselectAllInOrg(state())}
322322
disabled={
323323
visible().length === 0 ||
324324
visible().every((r) => !isSelected(r.fullName))
@@ -332,21 +332,21 @@ export default function RepoSelector(props: RepoSelectorProps) {
332332
</div>
333333

334334
{/* Loading state for this org */}
335-
<Show when={state.loading}>
335+
<Show when={state().loading}>
336336
<div class="flex justify-center py-6">
337337
<LoadingSpinner size="sm" label="Loading..." />
338338
</div>
339339
</Show>
340340

341341
{/* Error state for this org */}
342-
<Show when={!state.loading && state.error !== null}>
342+
<Show when={!state().loading && state().error !== null}>
343343
<div class="flex items-center justify-between px-4 py-3">
344344
<span class="text-sm text-red-600 dark:text-red-400">
345-
{state.error}
345+
{state().error}
346346
</span>
347347
<button
348348
type="button"
349-
onClick={() => retryOrg(state.org)}
349+
onClick={() => retryOrg(state().org)}
350350
class="ml-3 text-xs font-medium text-blue-600 hover:underline dark:text-blue-400"
351351
>
352352
Retry
@@ -355,7 +355,7 @@ export default function RepoSelector(props: RepoSelectorProps) {
355355
</Show>
356356

357357
{/* Repo list */}
358-
<Show when={!state.loading && state.error === null}>
358+
<Show when={!state().loading && state().error === null}>
359359
<Show
360360
when={visible().length > 0}
361361
fallback={
@@ -369,8 +369,8 @@ export default function RepoSelector(props: RepoSelectorProps) {
369369
<div
370370
class="max-h-[300px] overflow-y-auto"
371371
role="region"
372-
aria-label={`${state.org} repositories`}
373-
data-testid={`repo-scroll-${state.org}`}
372+
aria-label={`${state().org} repositories`}
373+
data-testid={`repo-scroll-${state().org}`}
374374
>
375375
<ul class="divide-y divide-gray-100 dark:divide-gray-700">
376376
<Index each={visible()}>
@@ -408,7 +408,7 @@ export default function RepoSelector(props: RepoSelectorProps) {
408408
</div>
409409
);
410410
}}
411-
</For>
411+
</Index>
412412

413413
{/* Total count */}
414414
<Show when={!isLoadingAny() && props.selected.length > 0}>

0 commit comments

Comments
 (0)