From 4e8beae209e55f45fbe43f87c6f10d56a139c387 Mon Sep 17 00:00:00 2001 From: Developer Date: Wed, 11 Mar 2026 14:48:19 +0800 Subject: [PATCH] fix: add unmount cancellation guard, simplify keyExtractor, update spec --- app/index.tsx | 4 ++-- components/BigVideoCard.tsx | 16 ++++++++-------- .../specs/2026-03-11-big-video-card-design.md | 2 +- 3 files changed, 11 insertions(+), 11 deletions(-) diff --git a/app/index.tsx b/app/index.tsx index 67affe5..0b8bef1 100644 --- a/app/index.tsx +++ b/app/index.tsx @@ -99,10 +99,10 @@ export default function HomeScreen() { + keyExtractor={(row: any) => row.type === 'big' ? `big-${row.item.bvid}` - : `pair-${row.left.bvid}-${row.right?.bvid ?? 'empty'}-${index}` + : `pair-${row.left.bvid}-${row.right?.bvid ?? 'empty'}` } contentContainerStyle={{ paddingTop: insets.top + NAV_H + 6, diff --git a/components/BigVideoCard.tsx b/components/BigVideoCard.tsx index c8a0943..0e820cc 100644 --- a/components/BigVideoCard.tsx +++ b/components/BigVideoCard.tsx @@ -45,7 +45,7 @@ export function BigVideoCard({ item, isVisible, onPress }: Props) { // Fetch play URL when visible for the first time useEffect(() => { if (!isVisible || videoUrl) return; - + let cancelled = false; (async () => { try { // cid may be missing from feed items; fetch detail if needed @@ -54,25 +54,25 @@ export function BigVideoCard({ item, isVisible, onPress }: Props) { const detail = await getVideoDetail(item.bvid); cid = detail.cid ?? detail.pages?.[0]?.cid; } - if (!cid) return; - + if (!cid || cancelled) return; const playData = await getPlayUrl(item.bvid, cid, 16); - + if (cancelled) return; if (playData.dash) { - setIsDash(true); + if (!cancelled) setIsDash(true); try { const mpdUri = await buildDashMpdUri(playData, 16); - setVideoUrl(mpdUri); + if (!cancelled) setVideoUrl(mpdUri); } catch { - setVideoUrl(playData.dash.video[0]?.baseUrl); + if (!cancelled) setVideoUrl(playData.dash.video[0]?.baseUrl); } } else { - setVideoUrl(playData.durl?.[0]?.url); + if (!cancelled) setVideoUrl(playData.durl?.[0]?.url); } } catch (e) { console.warn('BigVideoCard: failed to load play URL', e); } })(); + return () => { cancelled = true; }; // videoUrl intentionally excluded — re-fetch guard prevents redundant fetches after URL is set }, [isVisible, item.bvid]); diff --git a/docs/superpowers/specs/2026-03-11-big-video-card-design.md b/docs/superpowers/specs/2026-03-11-big-video-card-design.md index 21f6391..a9c04ae 100644 --- a/docs/superpowers/specs/2026-03-11-big-video-card-design.md +++ b/docs/superpowers/specs/2026-03-11-big-video-card-design.md @@ -53,7 +53,7 @@ interface BigVideoCardProps { ``` BigVideoCard (TouchableOpacity) ├── 封面图 (Image, 16:9 全宽) -├── 视频播放器 (NativeVideoPlayer, position: absolute, isVisible 时加载) +├── 视频播放器 (react-native-video