fix(tasks): key pagination resets on repo selection, not array identity

The repos store installs a fresh array on every repos:changed event, so
the pagination-reset effect fired on background refreshes and bumped the
request generation, silently discarding any in-flight page navigation —
clicking an unloaded page did nothing whenever a repo refresh landed
during the fetch. Key the effect on the stable selection string instead.
This commit is contained in:
Brennan Benson
2026-07-30 06:50:32 -07:00
parent 6bccdbc12f
commit 8a31aaf4e1
+15 -10
View File
@@ -3205,6 +3205,17 @@ export default function TaskPage(): React.JSX.Element {
[eligibleRepos, repoSelection]
)
// Why: stable string key for selectedRepos — the repos store installs a fresh
// array on every repos:changed event, so array-identity deps re-fire even when
// the selection is unchanged.
const selectedReposKey = useMemo(
() =>
selectedRepos
.map((r) => `${r.id}|${r.path}|${r.connectionId ?? ''}|${r.executionHostId ?? ''}`)
.join(','),
[selectedRepos]
)
// Why: many affordances need *a* repo; use the first selected as default, while cross-repo dialogs still let the user override per-action.
const primaryRepo = selectedRepos[0] ?? null
const linearWorkspaces = linearStatus.workspaces ?? []
@@ -3810,11 +3821,14 @@ export default function TaskPage(): React.JSX.Element {
const fetchWorkItemsNextPage = useAppStore((s) => s.fetchWorkItemsNextPage)
const countWorkItemsAcrossRepos = useAppStore((s) => s.countWorkItemsAcrossRepos)
// Why: keyed on selectedReposKey, not the selectedRepos array — a background
// repos:changed refresh mid-flight would otherwise bump the generation and
// silently discard the user's page navigation (#11485).
useEffect(() => {
paginationGenerationRef.current += 1
setPaginationLoading(false)
setLoadingTargetPage(null)
}, [selectedRepos, appliedTaskSearch, workItemsInvalidationNonce])
}, [selectedReposKey, appliedTaskSearch, workItemsInvalidationNonce])
// Why: the dialog's "Use" button routes through the same direct-launch flow as the row-level "Use" CTA so behavior is consistent regardless of entry point.
const githubTaskDrawerWorkItem = useAppStore((s) => s.githubTaskDrawerWorkItem)
@@ -4829,15 +4843,6 @@ export default function TaskPage(): React.JSX.Element {
jiraTaskSourceContext
])
// Why: stable string key for selectedRepos so the GitLab effect doesn't re-run on every parent render from a new array ref.
const selectedReposKey = useMemo(
() =>
selectedRepos
.map((r) => `${r.id}|${r.path}|${r.connectionId ?? ''}|${r.executionHostId ?? ''}`)
.join(','),
[selectedRepos]
)
// Why: fetch GitLab Issues and MRs separately so errors stay isolated per tab (mirrors GitHub's split endpoints).
useEffect(() => {
if (taskSource !== 'gitlab') {