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

React Native中react-native-video点击播放所有视频同步触发问题

问题原因

所有列表项内的Video组件共用了顶层声明的同一个paused布尔状态,状态更新时所有组件读取到的暂停值同步变化,就会出现全列表视频同步播放/暂停的现象。另外原代码map遍历返回了相邻的两个同级组件,没有外层包裹节点,会触发JSX语法报错,需要给每个列表项增加唯一根节点。

解决方案

根据实际交互需求二选一即可:

方案1:同一时间仅允许单个视频播放(短视频类列表通用交互)

将原本存储布尔值的状态改为存储当前处于播放状态的视频唯一标识(比如视频ID,不要用不稳定的数组索引),判断单个视频是否暂停时,仅需对比当前视频标识和状态内存储的激活播放标识是否一致即可,点按播放新视频时会自动暂停其他正在播放的视频。
修改后代码参考:

// 存储当前激活播放的视频ID,默认值为null代表所有视频初始为暂停状态
const [activeVideoId, setActiveVideoId] = useState(null);

// 切换视频播放状态,传入当前操作的视频ID
const toggleVideoPlay = (videoId) => {
  setActiveVideoId(prev => prev === videoId ? null : videoId);
}

{videos.map((video) => {
  const isPaused = activeVideoId !== video.id;
  return (
    <View key={video.id} style={styles.videoContainer}>
      <Video
        source={{ uri: video.video }}
        rate={1.0}
        volume={1.0}
        resizeMode="cover"
        style={styles.video}
        paused={isPaused}
        onEnd={() => setActiveVideoId(null)}
      />
      {isPaused && (
        <View style={styles.videoPause}>
          <Text style={styles.title}>{video.titulo}</Text>
          <Text style={styles.description}>{video.descripcion}</Text>
          <TouchableOpacity 
            style={styles.playButton} 
            onPress={() => toggleVideoPlay(video.id)}
          >
            <CustomIcon name="play" size={90} color={'#fff'} />
          </TouchableOpacity>
        </View>
      )}
    </View>
  )
})}

方案2:支持多个视频同时独立控制播放状态

如果业务场景需要允许多个视频同时播放,不要把播放状态放在列表顶层维护,将单个视频的播放逻辑抽离为独立子组件,每个组件内部维护自身的播放状态,组件之间状态互不干扰。
子组件实现参考:

// 单个视频项组件,独立维护自身播放状态
const VideoItem = ({ video }) => {
  const [paused, setPaused] = useState(true);
  const togglePlay = () => setPaused(prev => !prev);

  return (
    <View style={styles.videoContainer}>
      <Video
        source={{ uri: video.video }}
        rate={1.0}
        volume={1.0}
        resizeMode="cover"
        style={styles.video}
        paused={paused}
        onEnd={() => setPaused(true)}
      />
      {paused && (
        <View style={styles.videoPause}>
          <Text style={styles.title}>{video.titulo}</Text>
          <Text style={styles.description}>{video.descripcion}</Text>
          <TouchableOpacity 
            style={styles.playButton} 
            onPress={togglePlay}
          >
            <CustomIcon name="play" size={90} color={'#fff'} />
          </TouchableOpacity>
        </View>
      )}
    </View>
  )
}

// 列表页遍历时直接渲染子组件即可
{videos.map((video) => <VideoItem key={video.id} video={video} />)}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.26 18:18:53