From 5ac9e678609d931b36cf1fcefdb86cdbc0bfe44a Mon Sep 17 00:00:00 2001 From: SkateSpots Date: Tue, 27 Oct 2026 16:43:49 +0700 Subject: [PATCH] fix(cordn): keep the invite poll alive across re-renders --- src/components/crew/CordnNativePanel.tsx | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/src/components/crew/CordnNativePanel.tsx b/src/components/crew/CordnNativePanel.tsx index 46a4116..3d31fb6 100644 --- a/src/components/crew/CordnNativePanel.tsx +++ b/src/components/crew/CordnNativePanel.tsx @@ -214,6 +214,13 @@ export function CordnNativePanel({ crew, canManage, isMember }: CordnNativePanel if (!awaiting) setNotice(t('cordnUi.noInvite')); }, [checkNow, awaiting, t, native.busy]); + // Keep the latest checker in a ref: the poll must not restart just because a + // parent re-render gave the hook callbacks new identities. + const checkNowRef = useRef(checkNow); + useEffect(() => { + checkNowRef.current = checkNow; + }, [checkNow]); + // Poll the coordinator while a join request is pending. Backs off from 10s to // 30s so a founder who approves later is picked up without a manual tap. // Interactive signers (Amber) are excluded — polling would pop their signer. @@ -225,7 +232,7 @@ export function CordnNativePanel({ crew, canManage, isMember }: CordnNativePanel const tick = async () => { if (cancelled) return; - const joined = await checkNow(); + const joined = await checkNowRef.current(); if (cancelled) return; if (joined) { setAwaiting(false); @@ -241,7 +248,7 @@ export function CordnNativePanel({ crew, canManage, isMember }: CordnNativePanel cancelled = true; if (timer !== undefined) window.clearTimeout(timer); }; - }, [awaiting, native.group, native.ready, native.interactiveHintVisible, checkNow]); + }, [awaiting, native.group, native.ready, native.interactiveHintVisible]); // "Join our crew chat" invite. The chat needs the person to be a crew member // first, so the link just drops them on this crew's private-chat tab with the