React Native:从MyVideo返回后刷新MyVideoList组件的可行方案
解决React Native导航返回后列表刷新问题的可行方案
下面是几个能解决你问题的具体方案,避开之前遇到的序列化警告和Hook调用错误:
方法1:用useFocusEffect监听屏幕焦点,重新获取数据
利用React Navigation提供的useFocusEffect钩子,每次MyVideoList屏幕获得焦点时,重新拉取或更新视频数据,确保显示最新的lastViewed状态。
import { useFocusEffect } from '@react-navigation/native'; import { useState, useCallback } from 'react'; function MyVideoList() { const [videos, setVideos] = useState(初始视频数组); // 每次屏幕聚焦时更新数据 useFocusEffect( useCallback(() => { // 这里替换成你获取最新视频数据的逻辑,比如从本地存储/接口拉取 const getUpdatedVideos = async () => { const latestVideos = await 你的数据获取函数(); setVideos(latestVideos); }; getUpdatedVideos(); }, []) ); // 渲染视频列表... }
这个方案不用传递回调,也不依赖全局状态,完全规避序列化问题,Hook调用也符合规则。
方法2:返回时通过导航参数传递更新信息
不用goBack,改用navigate回到列表页并携带更新的视频ID,列表页监听参数变化来更新状态。
MyVideo组件的返回逻辑:
// 播放结束后触发 navigation.navigate('MyVideoList', { updatedVideoId: 'Video2' });
MyVideoList组件监听参数:
import { useRoute } from '@react-navigation/native'; import { useEffect, useState } from 'react'; function MyVideoList() { const [videos, setVideos] = useState(初始视频数组); const route = useRoute(); useEffect(() => { if (route.params?.updatedVideoId) { // 更新视频列表,标记最新观看的视频为current setVideos(prevVideos => prevVideos.map(video => video.id === route.params.updatedVideoId ? { ...video, lastViewed: Date.now(), isCurrent: true } : { ...video, isCurrent: false } )); // 清除参数,避免重复触发更新 navigation.setParams({ updatedVideoId: undefined }); } }, [route.params?.updatedVideoId]); // 渲染列表... }
传递的参数是可序列化的字符串/数字,不会触发导航状态的序列化警告,实现简单直接。
方法3:用React Context管理全局视频状态
用React原生的Context API替代Redux,全局共享视频状态,播放结束后直接更新Context,列表页会自动刷新。
先创建视频Context:
// VideoContext.js import { createContext, useContext, useState } from 'react'; const VideoContext = createContext(); export function VideoProvider({ children }) { const [videos, setVideos] = useState(初始视频数组); // 更新视频观看状态的方法 const updateVideoLastViewed = (videoId) => { setVideos(prev => prev.map(video => video.id === videoId ? { ...video, lastViewed: Date.now(), isCurrent: true } : { ...video, isCurrent: false } )); }; return ( <VideoContext.Provider value={{ videos, updateVideoLastViewed }}> {children} </VideoContext.Provider> ); } // 自定义Hook,简化Context调用 export function useVideoContext() { return useContext(VideoContext); }
在App外层包裹Provider:
import { VideoProvider } from './VideoContext'; import { NavigationContainer } from '@react-navigation/native'; function App() { return ( <VideoProvider> <NavigationContainer> {/* 你的路由配置 */} </NavigationContainer> </VideoProvider> ); }
MyVideo组件里更新状态:
import { useVideoContext } from './VideoContext'; function MyVideo({ route, navigation }) { const { updateVideoLastViewed } = useVideoContext(); const videoId = route.params.videoId; // 播放结束回调 const onPlayFinish = () => { updateVideoLastViewed(videoId); navigation.goBack(); }; // 渲染播放组件... }
MyVideoList组件直接用Context状态:
import { useVideoContext } from './VideoContext'; import { FlatList } from 'react-native'; function MyVideoList() { const { videos } = useVideoContext(); return ( <FlatList data={videos} renderItem={({ item }) => ( <View style={{ backgroundColor: item.isCurrent ? 'green' : 'white' }}> {/* 视频项内容 */} </View> )} /> ); }
Context是React原生方案,只要在函数组件内正确使用Hook,就不会出现Hook调用错误,状态更新后组件自动刷新,也没有序列化问题。
方法4:本地存储(AsyncStorage/MMKV)存储数据,返回时重新读取
如果视频数据存在本地存储,每次回到列表页时重新读取存储的数据,确保显示最新状态。
MyVideoList组件:
import { useFocusEffect } from '@react-navigation/native'; import { useState, useCallback } from 'react'; import AsyncStorage from '@react-native-async-storage/async-storage'; function MyVideoList() { const [videos, setVideos] = useState([]); useFocusEffect( useCallback(() => { const loadLatestVideos = async () => { const storedVideos = await AsyncStorage.getItem('videos'); if (storedVideos) { setVideos(JSON.parse(storedVideos)); } }; loadLatestVideos(); }, []) ); // 渲染列表... }
MyVideo组件播放结束后更新存储:
import AsyncStorage from '@react-native-async-storage/async-storage'; function MyVideo({ route, navigation }) { const videoId = route.params.videoId; const onPlayEnd = async () => { // 读取当前存储的视频数据 const storedVideos = await AsyncStorage.getItem('videos'); let videos = storedVideos ? JSON.parse(storedVideos) : []; // 更新对应视频的状态 videos = videos.map(video => video.id === videoId ? { ...video, lastViewed: Date.now(), isCurrent: true } : { ...video, isCurrent: false } ); // 存回本地存储 await AsyncStorage.setItem('videos', JSON.stringify(videos)); navigation.goBack(); }; // 渲染播放组件... }
这个方案适合数据量不大的场景,完全避开导航和状态管理的坑,逻辑直观。
内容的提问来源于stack exchange,提问作者Philippe
相关产品推荐
相关产品推荐

