You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.04 04:45:19