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

React Native中selectedItem状态变更时ActivityIndicator不显示的问题排查

问题分析与解决方案

我来帮你排查下这个问题,核心原因其实很简单——你在触发新的请求时没有重置isLoading状态!

具体问题拆解:

  1. 加载状态未重置:第一次渲染时isLoading初始为true,所以能正常显示加载指示器。但当selectedItem.status变化触发useEffect调用getItems时,你直接发起了API请求,却没有先把isLoading设为true,这时候界面还是保持之前的非加载状态,自然看不到ActivityIndicator。
  2. 空值访问风险:初始selectedItem是null,直接访问selectedItem.status会导致报错,而且useEffect的依赖数组里放这个值也会有稳定性问题。
  3. 数组判断逻辑错误:items !== []这个判断永远为true,因为两个数组是不同的引用,应该检查items是否存在且有实际内容。

修改后的代码:

import { useCallback, useEffect, useState } from 'react';
import { ActivityIndicator, SafeAreaView, SectionList, View, StyleSheet, Text } from 'react-native';

export default () => { 
  const [items, setItems] = useState([]); 
  const [selectedItem, setSelectedItem] = useState(null); 
  const [isLoading, setLoading] = useState(true); 

  // 用useCallback包裹,确保函数引用稳定,避免不必要的useEffect触发
  const getItems = useCallback(async () => { 
    // 发起请求前先设置加载状态为true,这是解决你问题的关键
    setLoading(true);
    try {
      const rep = await get('/api/items');
      setItems(rep);
    } catch (error) {
      // 别忘了处理请求失败的情况,避免一直显示加载
      console.error('Failed to fetch items:', error);
      // 可以在这里设置默认数据或者提示用户
    } finally {
      // 不管成功失败,都结束加载状态
      setLoading(false);
    }
  }, []);

  useEffect(() => { 
    // 先判断selectedItem是否存在,避免空值访问报错
    if (selectedItem) {
      getItems();
    }
  }, [selectedItem?.status, getItems]); // 用可选链访问status,加入getItems到依赖数组

  return ( 
    <SafeAreaView style={styles.container}> 
      {isLoading ? ( 
        <View style={styles.spinnerContainer}> 
          <ActivityIndicator size="large" color="#0000ff" /> 
        </View> 
      ) : (
        items.length > 0 ? (
          <SectionList 
            stickySectionHeadersEnabled={false} 
            style={{ paddingHorizontal: 20 }} 
            sections={items} 
            refreshing={isLoading} 
            keyExtractor={(item, index) => `${item}-${index}`} 
            // 这里补充你的renderItem等属性
          />
        ) : (
          // 没有数据时的友好提示
          <View style={styles.emptyContainer}>
            <Text>No items found</Text>
          </View>
        )
      )} 
    </SafeAreaView> 
  ); 
};

const styles = StyleSheet.create({
  container: {
    flex: 1,
  },
  spinnerContainer: {
    flex: 1,
    justifyContent: 'center',
    alignItems: 'center',
  },
  emptyContainer: {
    flex: 1,
    justifyContent: 'center',
    alignItems: 'center',
  },
});

关键修改点说明:

  • 重置加载状态:在getItems函数开头就调用setLoading(true),确保每次发起请求时都会显示加载指示器。
  • 异步逻辑优化:用async/await替代.then,让代码更易读,同时用try/catch/finally处理请求失败的情况,避免界面一直卡在加载状态。
  • 空值安全处理:用selectedItem?.status避免空值访问错误,在useEffect里先判断selectedItem存在才调用getItems。
  • 数组判断修正:用items.length > 0代替items !== [],正确判断是否有可用数据。
  • 函数稳定性保障:用useCallback包裹getItems,确保函数引用稳定,避免useEffect因为函数变化而不必要触发。

这样修改后,当selectedItem.status变化时,会重新发起请求并显示ActivityIndicator,加载完成后更新数据并隐藏指示器。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.29 13:37:34