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
相关产品推荐
相关产品推荐

