fix(native/community): sync foreign likes_count into PostCard.localCount

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.
This commit is contained in:
chahinebrini 2026-05-16 01:08:14 +02:00
parent 7c6b463acb
commit 500f673e53

View File

@ -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(() => {