auto-claude: 203-fix-ui-not-updating-during-pr-review-operations (#1733)

* auto-claude: subtask-1-1 - Replace blanket prReviews subscription with targeted selector

- Replace blanket prReviews subscription with targeted selector for selected PR
- Optimize selectedPRReviewState to only subscribe to specific PR's state changes
- Convert activePRReviews to use direct selector instead of useMemo
- Remove unnecessary prReviews dependency from getReviewStateForPR callback
- Reduces unnecessary re-renders when unrelated PR states change

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>

* fix: resolve PR review selector issues causing stale filtering and excess re-renders

- Restore prReviews dependency in getReviewStateForPR so usePRFiltering's
  memoized filteredPRs recomputes when review states change (fixes status
  filter not updating after review completion)
- Replace activePRReviews inline Zustand selector with useMemo to avoid
  creating new array references on every store change (the .filter().map()
  chain defeated Object.is equality, causing unnecessary re-renders)
- Read prReviews directly in both hooks instead of using store methods,
  making dependencies explicit and satisfying exhaustive-deps lint rule

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

---------

Co-authored-by: Test User <test@example.com>
Co-authored-by: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
Andy
2026-02-09 10:24:44 +01:00
committed by GitHub
parent f121f9cdd2
commit f085c08bd0
@@ -95,16 +95,17 @@ export function useGitHubPRs(
const fetchGenerationRef = useRef(0);
// Get PR review state from the global store
const _prReviews = usePRReviewStore((state) => state.prReviews);
const prReviews = usePRReviewStore((state) => state.prReviews);
const getPRReviewState = usePRReviewStore((state) => state.getPRReviewState);
const getActivePRReviews = usePRReviewStore((state) => state.getActivePRReviews);
const setNewCommitsCheckAction = usePRReviewStore((state) => state.setNewCommitsCheck);
// Get review state for the selected PR from the store
const selectedPRReviewState = useMemo(() => {
// Get review state for the selected PR from the store - optimized with targeted selector
// Only subscribes to changes for this specific PR, not all PRs
const selectedPRReviewState = usePRReviewStore((state) => {
if (!projectId || selectedPRNumber === null) return null;
return getPRReviewState(projectId, selectedPRNumber);
}, [projectId, selectedPRNumber, getPRReviewState]);
const key = `${projectId}:${selectedPRNumber}`;
return state.prReviews[key] || null;
});
// Derive values from store state - all from the same source to ensure consistency
const reviewResult = selectedPRReviewState?.result ?? null;
@@ -116,14 +117,19 @@ export function useGitHubPRs(
// Get list of PR numbers currently being reviewed
const activePRReviews = useMemo(() => {
if (!projectId) return [];
return getActivePRReviews(projectId).map((review) => review.prNumber);
}, [projectId, getActivePRReviews]);
return Object.values(prReviews)
.filter((review) => review.projectId === projectId && review.isReviewing)
.map((review) => review.prNumber);
}, [projectId, prReviews]);
// Helper to get review state for any PR
// Reads directly from prReviews so the callback invalidates when any review state changes,
// which is needed for usePRFiltering's memoized filteredPRs to recompute correctly
const getReviewStateForPR = useCallback(
(prNumber: number) => {
if (!projectId) return null;
const state = getPRReviewState(projectId, prNumber);
const key = `${projectId}:${prNumber}`;
const state = prReviews[key];
if (!state) return null;
return {
isReviewing: state.isReviewing,
@@ -135,7 +141,7 @@ export function useGitHubPRs(
newCommitsCheck: state.newCommitsCheck,
};
},
[projectId, getPRReviewState]
[projectId, prReviews]
);
// Use detailed PR data if available (includes files), otherwise fall back to list data