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

React Native:为每个视频单独控制Activity Indicator加载状态

这个问题我之前做视频列表的时候也踩过坑,全局状态确实没法单独控制每个视频的加载状态,咱们得把状态改成针对每个视频的独立存储才行!结合你的代码片段,给你两种场景的具体实现方法:

一、如果你用的是类组件(从this.removePrompt判断你大概率是类组件)

1. 初始化独立加载状态

把原来的单个loading状态,改成用对象存储每个视频的加载状态(用视频的唯一标识当key,比如你代码里的camera.title,如果有id优先用id更可靠):

constructor(props) {
  super(props);
  this.state = {
    // 键是视频的唯一标识,值是加载状态(true=加载中,false=加载完成)
    loadingStates: {}
  };
}

// 当视频列表数据更新时,自动给新视频初始化加载状态
componentDidUpdate(prevProps) {
  if (prevProps.revArray !== this.props.revArray) {
    const newLoadingStates = {...this.state.loadingStates};
    this.props.revArray.forEach(camera => {
      // 新视频默认设为加载中
      if (!(camera.title in newLoadingStates)) {
        newLoadingStates[camera.title] = true;
      }
    });
    this.setState({ loadingStates: newLoadingStates });
  }
}

2. 渲染时绑定对应状态并更新

在map渲染时,每个视频的ActivityIndicator显示状态绑定对应视频的loadingStates,并在视频onLoad回调里单独更新该视频的状态:

{revArray.map((camera, index) => (
  <View key={'camera'+index} style={{backgroundColor:'#eeeeee'}}>
    <TouchableOpacity onPress={() => {this.removePrompt(camera.title.toString())}} style={{padding:6}}>
      {/* 假设你的视频组件是Video,添加onLoad回调 */}
      <Video
        source={{ uri: camera.videoUrl }} // 替换成你的视频地址字段
        onLoad={() => {
          // 只更新当前视频的加载状态为false
          this.setState(prevState => ({
            loadingStates: {
              ...prevState.loadingStates,
              [camera.title]: false
            }
          }));
        }}
        // 其他视频属性(比如样式、播放设置)...
      />
      {/* 根据当前视频的加载状态显示Indicator */}
      {(this.state.loadingStates[camera.title] ?? true) && (
        <ActivityIndicator 
          style={{ position: 'absolute', top: '50%', left: '50%', transform: [{translateX: -15}, {translateY: -15}] }}
          size="small" 
          color="#0000ff" 
        />
      )}
    </TouchableOpacity>
  </View>
))}

二、如果是函数组件(参考方案)

用useState存储加载状态对象,useEffect监听列表数据更新初始化状态:

import { useState, useEffect } from 'react';

// ...组件内部
const [loadingStates, setLoadingStates] = useState({});

// 监听视频列表变化,初始化新视频的加载状态
useEffect(() => {
  const newLoadingStates = {...loadingStates};
  revArray.forEach(camera => {
    if (!(camera.title in newLoadingStates)) {
      newLoadingStates[camera.title] = true;
    }
  });
  setLoadingStates(newLoadingStates);
}, [revArray]);

// 渲染部分和类组件逻辑一致,只是状态更新方式变了
{revArray.map((camera, index) => (
  <View key={'camera'+index} style={{backgroundColor:'#eeeeee'}}>
    <TouchableOpacity onPress={() => {removePrompt(camera.title.toString())}} style={{padding:6}}>
      <Video
        source={{ uri: camera.videoUrl }}
        onLoad={() => {
          setLoadingStates(prev => ({
            ...prev,
            [camera.title]: false
          }));
        }}
      />
      {(loadingStates[camera.title] ?? true) && (
        <ActivityIndicator style={{ position: 'absolute', top: '50%', left: '50%' }} />
      )}
    </TouchableOpacity>
  </View>
))}

核心思路

不再用单个全局变量控制所有加载状态,而是给每个视频分配独立的状态项,通过唯一标识(比如title/id)关联,这样视频加载完成后只会修改自己对应的状态,不会影响其他视频的Indicator显示。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.25 08:10:31