From 500f673e53009d39e1bd3c4acc631a97c5ccf461 Mon Sep 17 00:00:00 2001 From: chahinebrini Date: Sat, 16 May 2026 01:08:14 +0200 Subject: [PATCH] fix(native/community): sync foreign likes_count into PostCard.localCount MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Pure additive change — wasLikingRef + a small useEffect right after the existing useState declarations. handleLike, the heart animation, localLike, the memo comparator, and the render path are not touched. Mechanism: - useCommunityRealtime already patches the React-Query cache on UPDATE events for rebreak.community_posts (the table IS in supabase_realtime — verified via pg_publication_tables on staging today). - The cache patch propagates to PostCard as a new post.likesCount prop. - The useState seed (post.likesCount on mount) was never re-read after the first render — the source of the bug. - The new useEffect mirrors post.likesCount into localCount with one guard: when isLiking transitions from true → false, skip the first run. The cache patch from our own action arrives ~100–300ms after the API response settles, so on the immediate run the prop is still stale; skipping prevents an overwrite of the value handleLike just set. The next prop change (cache patch arrival) re-fires the effect and syncs correctly. - Pure foreign likes (no own action in flight) sync immediately. Earlier attempts (4c4792c, d28d1f1) tried to refactor wider — both broke own-likes / comments / animations. This commit deliberately changes only the new code paths. --- apps/rebreak-native/components/PostCard.tsx | 25 +++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/apps/rebreak-native/components/PostCard.tsx b/apps/rebreak-native/components/PostCard.tsx index 8b6e6ce..6031889 100644 --- a/apps/rebreak-native/components/PostCard.tsx +++ b/apps/rebreak-native/components/PostCard.tsx @@ -30,6 +30,31 @@ function PostCardImpl({ post, onCommentPress }: Props) { const [localCount, setLocalCount] = useState(post.likesCount); const [isLiking, setIsLiking] = useState(false); + // Foreign-like count sync. When useCommunityRealtime patches the React-Query + // cache (UPDATE on community_posts → likes_count changed), the prop updates + // but localCount is seeded once via useState and stays stale. Sync it. + // + // The wasLikingRef trick: when isLiking goes true → false (own action just + // settled), the prop hasn't been patched yet by the realtime broadcast (it + // arrives ~100-300ms later as Supabase relays our own DB update back to us). + // We skip the FIRST useEffect run after the transition so we don't overwrite + // the value handleLike just set with the still-stale prop. The next prop + // change (= cache patch arriving) re-fires the effect and syncs correctly. + // For pure foreign likes (no own action in flight) the first run goes + // through directly. + const wasLikingRef = useRef(false); + useEffect(() => { + if (isLiking) { + wasLikingRef.current = true; + return; + } + if (wasLikingRef.current) { + wasLikingRef.current = false; + return; + } + setLocalCount(post.likesCount); + }, [post.likesCount, isLiking]); + // Heart-Pop Animation — Insta-Style: quick scale-up + spring-bounce back const heartScale = useRef(new Animated.Value(1)).current; const triggerHeartPop = useCallback(() => {