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

React Native中React Navigation beforeRemove调用Video播放时长方法的问题

解决方案

要实现关闭Page页面时获取视频播放时长,核心是让Page组件能访问Video组件的方法,同时在页面即将移除时触发统计逻辑,具体步骤如下:

1. 改造Video组件,暴露播放时长方法

函数组件默认不支持ref,需用forwardRef和useImperativeHandle将getSeconds方法暴露给父组件:

// Video.js
import React, { forwardRef, useImperativeHandle, useRef, useState } from 'react';
import { Video } from 'expo-av';
import ExpoVideoPlayer from 'expo-video-player';

const VideoComponent = forwardRef((props, ref) => {
  const video = useRef(null);
  const [secondsPlayed, setSecondsPlayed] = useState(0);

  // 监听播放进度,实时更新播放时长
  const onPlaybackStatusUpdate = (status) => {
    if (status.isPlaying) {
      setSecondsPlayed(Math.floor(status.positionMillis / 1000));
    }
  };

  // 定义要暴露的方法
  const getSeconds = () => {
    return secondsPlayed;
  };

  // 向父组件暴露方法
  useImperativeHandle(ref, () => ({
    getSeconds
  }));

  return (
    <ExpoVideoPlayer
      videoProps={{
        resizeMode: Video.RESIZE_MODE_STRETCH,
        source: { uri: props.videoUrl },
        onPlaybackStatusUpdate: onPlaybackStatusUpdate
      }}
      inFullscreen={false}
      showControlsOnLoad={true}
      videoBackground="#fff"
      height={200}
      videoRef={video}
      showFullscreenButton={false}
      playIcon={() => props.playIcon}
      replayIcon={() => props.replayIcon}
      pauseIcon={() => props.pauseIcon}
      sliderColor="#CE4A52"
    />
  );
});

export default VideoComponent;

2. 在Page组件中关联Video实例并监听页面移除事件

在Page组件中创建ref绑定Video组件,通过navigation.addListener监听beforeRemove事件,调用Video的方法获取时长:

// Page.js
import React, { useRef, useEffect } from 'react';
import { SafeAreaView } from 'react-native';
import VideoComponent from './Video';

const Page = ({ navigation }) => {
  const videoRef = useRef(null);

  useEffect(() => {
    // 添加页面移除监听
    const unsubscribe = navigation.addListener('beforeRemove', () => {
      const playedSeconds = videoRef.current?.getSeconds();
      console.log('视频播放时长:', playedSeconds, '秒');
    });

    // 组件卸载时清理监听器
    return unsubscribe;
  }, [navigation]);

  return (
    <SafeAreaView>
      {/* 传递ref给Video组件 */}
      <VideoComponent 
        ref={videoRef}
        videoUrl="你的视频地址"
        playIcon={/* 自定义播放图标 */}
        replayIcon={/* 自定义重播图标 */}
        pauseIcon={/* 自定义暂停图标 */}
      />
    </SafeAreaView>
  );
};

export default Page;

3. 移除导航配置中的beforeRemove监听器

由于已在Page内部实现监听,Stack导航配置里的对应代码可删除:

// Stack导航配置
<Stack.Screen
  name="Page"
  component={Page}
  options={{ headerShown: false }}
  // 移除原listeners配置
/>

关键说明

  • 导航层的beforeRemove监听器无法直接访问Page内部的子组件实例,将逻辑移到Page组件内更合理。
  • forwardRef+useImperativeHandle是函数组件间实现父调用子方法的标准方式。
  • 必须通过onPlaybackStatusUpdate实时更新播放时长,确保获取的是最新数据。

内容的提问来源于stack exchange,提问作者jNiuk

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.15 20:33:39