Prevent a feedback loop between remote selection and refresh effects in PullRequestSection. This keeps refresh callback dependencies stable and avoids repeated state updates that triggered maximum update depth errors in desktop Git PR view.
This commit is contained in:
@@ -416,6 +416,7 @@ export const PullRequestSection: React.FC<{
|
|||||||
const lastRefreshAtRef = React.useRef(0);
|
const lastRefreshAtRef = React.useRef(0);
|
||||||
const lastDiscoveryPollAtRef = React.useRef(0);
|
const lastDiscoveryPollAtRef = React.useRef(0);
|
||||||
const statusRef = React.useRef<GitHubPullRequestStatus | null>(null);
|
const statusRef = React.useRef<GitHubPullRequestStatus | null>(null);
|
||||||
|
const selectedRemoteNameRef = React.useRef<string | null>(selectedRemote?.name ?? null);
|
||||||
const attemptedBodyHydrationRef = React.useRef<Set<string>>(new Set());
|
const attemptedBodyHydrationRef = React.useRef<Set<string>>(new Set());
|
||||||
const lastSyncedPrNumberRef = React.useRef<number | null>(null);
|
const lastSyncedPrNumberRef = React.useRef<number | null>(null);
|
||||||
|
|
||||||
@@ -926,6 +927,10 @@ export const PullRequestSection: React.FC<{
|
|||||||
statusRef.current = status;
|
statusRef.current = status;
|
||||||
}, [status]);
|
}, [status]);
|
||||||
|
|
||||||
|
React.useEffect(() => {
|
||||||
|
selectedRemoteNameRef.current = selectedRemote?.name ?? null;
|
||||||
|
}, [selectedRemote?.name]);
|
||||||
|
|
||||||
const refresh = React.useCallback(async (options?: { force?: boolean; onlyExistingPr?: boolean; silent?: boolean; markInitialResolved?: boolean }) => {
|
const refresh = React.useCallback(async (options?: { force?: boolean; onlyExistingPr?: boolean; silent?: boolean; markInitialResolved?: boolean }) => {
|
||||||
if (!canShow) return;
|
if (!canShow) return;
|
||||||
if (options?.onlyExistingPr && !statusRef.current?.pr) {
|
if (options?.onlyExistingPr && !statusRef.current?.pr) {
|
||||||
@@ -967,7 +972,7 @@ export const PullRequestSection: React.FC<{
|
|||||||
}
|
}
|
||||||
setError(null);
|
setError(null);
|
||||||
try {
|
try {
|
||||||
const next = await github.prStatus(directory, branch, selectedRemote?.name);
|
const next = await github.prStatus(directory, branch, selectedRemoteNameRef.current ?? undefined);
|
||||||
setStatus((prev) => {
|
setStatus((prev) => {
|
||||||
const nextPr = next.pr;
|
const nextPr = next.pr;
|
||||||
const prevPr = prev?.pr;
|
const prevPr = prev?.pr;
|
||||||
@@ -1014,11 +1019,11 @@ export const PullRequestSection: React.FC<{
|
|||||||
}
|
}
|
||||||
isRefreshInFlightRef.current = false;
|
isRefreshInFlightRef.current = false;
|
||||||
}
|
}
|
||||||
}, [branch, canShow, directory, github, githubAuthChecked, githubAuthStatus, selectedRemote?.name]);
|
}, [branch, canShow, directory, github, githubAuthChecked, githubAuthStatus]);
|
||||||
|
|
||||||
// Refetch PR status when selected remote changes
|
// Refetch PR status when selected remote changes
|
||||||
const handleRemoteChange = React.useCallback((remote: GitRemote) => {
|
const handleRemoteChange = React.useCallback((remote: GitRemote) => {
|
||||||
setSelectedRemote(remote);
|
setSelectedRemote((prev) => (prev?.name === remote.name ? prev : remote));
|
||||||
// Clear current status and refetch
|
// Clear current status and refetch
|
||||||
setStatus(null);
|
setStatus(null);
|
||||||
setError(null);
|
setError(null);
|
||||||
@@ -1032,24 +1037,26 @@ export const PullRequestSection: React.FC<{
|
|||||||
setBody(snapshot?.body ?? '');
|
setBody(snapshot?.body ?? '');
|
||||||
setDraft(snapshot?.draft ?? false);
|
setDraft(snapshot?.draft ?? false);
|
||||||
setTargetBaseBranch(snapshot?.targetBaseBranch ? normalizeBranchRef(snapshot.targetBaseBranch) : normalizeBranchRef(baseBranch));
|
setTargetBaseBranch(snapshot?.targetBaseBranch ? normalizeBranchRef(snapshot.targetBaseBranch) : normalizeBranchRef(baseBranch));
|
||||||
setSelectedRemote(
|
const nextRemote = pickInitialPrRemote(remotes, {
|
||||||
pickInitialPrRemote(remotes, {
|
selectedRemoteName: snapshot?.selectedRemoteName,
|
||||||
selectedRemoteName: snapshot?.selectedRemoteName,
|
trackingBranch,
|
||||||
trackingBranch,
|
});
|
||||||
})
|
setSelectedRemote((prev) => (prev?.name === nextRemote?.name ? prev : nextRemote));
|
||||||
);
|
|
||||||
setStatus(statusSnapshot);
|
setStatus(statusSnapshot);
|
||||||
setError(null);
|
setError(null);
|
||||||
setIsInitialStatusResolved(Boolean(statusSnapshot));
|
setIsInitialStatusResolved(Boolean(statusSnapshot));
|
||||||
|
}, [baseBranch, branch, remotes, snapshotKey, trackingBranch]);
|
||||||
|
|
||||||
|
React.useEffect(() => {
|
||||||
void refresh({ force: true, markInitialResolved: true });
|
void refresh({ force: true, markInitialResolved: true });
|
||||||
}, [baseBranch, branch, refresh, remotes, snapshotKey, trackingBranch]);
|
}, [snapshotKey, refresh]);
|
||||||
|
|
||||||
// Refetch when selected remote changes
|
// Refetch when selected remote changes
|
||||||
React.useEffect(() => {
|
React.useEffect(() => {
|
||||||
if (selectedRemote) {
|
if (selectedRemote?.name) {
|
||||||
void refresh({ force: true, markInitialResolved: true });
|
void refresh({ force: true, markInitialResolved: true });
|
||||||
}
|
}
|
||||||
}, [selectedRemote, refresh]);
|
}, [selectedRemote?.name, refresh]);
|
||||||
|
|
||||||
React.useEffect(() => {
|
React.useEffect(() => {
|
||||||
const onFocus = () => {
|
const onFocus = () => {
|
||||||
|
|||||||
Reference in New Issue
Block a user