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

React Native Expo应用:文章页面加载时显示ActivityIndicator求助

修复后的React Native Expo 文章列表与详情页代码

我来帮你搞定代码里的问题,同时实现详情页加载时显示ActivityIndicator的需求:

先梳理下原代码里的几个关键问题:

  • HomeScreen作为类组件,不能在类的直接作用域里写const { navigate } = this.props.navigation;,必须放到render方法内部
  • ArticleScreen里写了两个return语句,这是语法错误,第二个return永远不会被执行
  • 详情页的参数没有正确保存到组件状态中,导致无法渲染内容
  • 传递参数时可以直接传递整个rowData,不用逐个字段拆解,更简洁

下面是修改后的完整代码:

import React from 'react';
import { SafeAreaView, ScrollView, ListView, TouchableOpacity, Image, Text, View, ActivityIndicator } from 'react-native';

// 首页文章列表组件
class HomeScreen extends React.Component {
  render() {
    // 把navigate的获取放到render方法内部,符合类组件语法规范
    const { navigate } = this.props.navigation;

    return (
      <SafeAreaView style={styles.MainContainer}>
        <ScrollView>
          <ListView
            dataSource={this.state.dataSource}
            renderSeparator={this.ListViewItemSeparator}
            renderRow={(rowData) => (
              <TouchableOpacity
                style={{ flex: 2 }}
                activeOpacity={0.7}
                // 直接传递整个rowData对象,后续新增字段无需修改跳转逻辑
                onPress={() => navigate('Articles', { articleData: rowData })}
              >
                <Image
                  source={{ uri: rowData.mobile_image }}
                  style={{
                    resizeMode: 'cover',
                    width: null,
                    height: null,
                    flex: 1,
                    borderRadius: 4,
                    borderWidth: 1,
                    borderColor: '#dddddd'
                  }}
                />
                <Text style={styles.textOfArticle}> {rowData.article_title} </Text>
              </TouchableOpacity>
            )}
          />
        </ScrollView>
      </SafeAreaView>
    );
  }
}

// 文章详情页组件
class ArticleScreen extends React.Component {
  static navigationOptions = ({ navigation }) => {
    const { params } = navigation.state;
    return {
      // 用可选链避免空值报错,默认显示空标题
      title: params?.articleData?.article_title || '',
    };
  };

  state = {
    animating: true,
    articleData: null // 存储传递过来的文章数据
  };

  componentDidMount() {
    // 获取导航传递的参数
    const { params } = this.props.navigation.state;
    // 把文章数据存入状态,更新完成后关闭加载指示器
    this.setState({
      articleData: params?.articleData || null
    }, () => {
      this.closeActivityIndicator();
    });

    // 如果需要模拟异步加载(比如从网络请求详情),可以取消下面的注释
    // setTimeout(() => {
    //   this.closeActivityIndicator();
    // }, 1000);
  }

  closeActivityIndicator = () => {
    this.setState({ animating: false });
  };

  render() {
    const { animating, articleData } = this.state;

    // 加载中或数据未准备好时,只显示ActivityIndicator
    if (animating || !articleData) {
      return (
        <View style={styles.container}>
          <ActivityIndicator
            animating={animating}
            color='#bc2b78'
            size="large"
            style={styles.activityIndicator}
          />
        </View>
      );
    }

    // 数据准备完成,渲染文章详情
    return (
      <SafeAreaView>
        <ScrollView>
          <Image
            source={{ uri: articleData.mobile_image }}
            style={{
              resizeMode: 'cover',
              width: '100%',
              height: 200,
              borderRadius: 4,
              borderWidth: 1,
              borderColor: '#dddddd'
            }}
          />
          <Text style={{ fontSize: 20, fontWeight: 'bold', margin: 10 }}>
            {articleData.article_title}
          </Text>
          <Text style={{ marginHorizontal: 10, color: '#666', marginBottom: 10 }}>
            分类: {articleData.article_category} | 浏览量: {articleData.views}
          </Text>
          <Text style={{ margin: 10, lineHeight: 22 }}>
            {articleData.article_content}
          </Text>
        </ScrollView>
      </SafeAreaView>
    );
  }
}

// 自定义样式,可根据需求调整
const styles = {
  MainContainer: {
    flex: 1,
    padding: 10
  },
  textOfArticle: {
    fontSize: 16,
    padding: 10,
    color: '#333'
  },
  container: {
    flex: 1,
    justifyContent: 'center',
    alignItems: 'center'
  },
  activityIndicator: {
    flex: 1,
    justifyContent: 'center',
    alignItems: 'center',
    height: 80
  }
};

export { HomeScreen, ArticleScreen };

关键修改说明:

  1. HomeScreen优化:

    • 修正了类组件的语法错误,将navigate的获取移到render方法内
    • 跳转时直接传递整个文章对象,简化参数传递逻辑
  2. ArticleScreen修复与优化:

    • 移除了重复的return语句,改用条件渲染实现加载状态切换
    • 将文章数据存入组件状态,确保渲染时能正常读取
    • 使用可选链操作符?.避免空值报错,提升代码健壮性
    • 完善了详情页的UI展示,补充了分类、浏览量等信息的渲染
  3. 加载逻辑:

    • 如果详情页需要从网络请求额外数据,可将异步请求放到componentDidMount中,请求完成后再关闭指示器(代码中保留了模拟示例)

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.13 08:21:48