本文还有配套的精品资源,点击获取 menu-r.4af5f7ec.gif

简介:React Native是由Facebook推出的开源框架,允许开发者使用JavaScript和React构建原生移动应用。本示例提供一个功能相对完整的新闻发布类型应用,涵盖React Native的核心概念与开发流程。内容包括UI组件构建、导航实现、样式设计、数据获取与状态管理、错误处理、第三方库集成及应用打包发布等模块,适合开发者深入学习并掌握React Native在实际项目中的应用技巧。
一个相对比较完整的ReactNative应用示例一个新闻发布类型的应用

1. React Native基础与核心概念

React Native 是由 Facebook 推出的开源框架,允许开发者使用 JavaScript 构建原生渲染的跨平台移动应用。其核心思想是“一次编写,多端运行”,通过桥接机制将 JavaScript 逻辑与原生组件进行通信,实现接近原生的性能与体验。

1.1 React Native 与原生开发对比

特性 原生开发(Java/Swift) React Native
开发效率
跨平台能力 支持 Android & iOS
性能 接近原生
组件更新与热重载 不支持 支持
社区生态 丰富

React Native 的最大优势在于 代码复用率高 开发周期短 ,适合 MVP 快速开发和中小型项目。对于需要极致性能的场景(如复杂动画、游戏),原生开发仍然是更优选择。

1.2 JavaScript 与 React 框架基础

React Native 基于 React 框架,因此掌握 React 的核心理念至关重要:

  • 组件化开发 :将 UI 拆分为独立、可复用的组件。
  • JSX 语法 :在 JavaScript 中嵌入类似 HTML 的结构。
  • 虚拟 DOM / React Fiber :用于优化渲染性能。

React 的核心思想是: 声明式 UI + 单向数据流 + 组件化架构

例如,一个最简单的 React Native 组件如下:

import React from 'react';
import { View, Text } from 'react-native';

const App = () => {
  return (
    <View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
      <Text>Hello, React Native!</Text>
    </View>
  );
};

export default App;
  • View 类似 HTML 的 div ,用于布局容器。
  • Text 用于显示文本内容。
  • style 属性接受一个对象,用于定义组件样式。

该示例在屏幕上居中显示文本“Hello, React Native!”,是构建界面的最基础结构。

1.3 React Native 的工作原理

React Native 并非 WebView 应用,其底层通过 JavaScript 引擎(如 Hermes、JSC)与原生平台通信,使用“桥接(Bridge)”机制将 JavaScript 逻辑转换为原生组件调用。

核心流程如下:

graph LR
  A[JavaScript代码] --> B(JavaScript引擎)
  B --> C[桥接层Bridge]
  C --> D[原生模块]
  D --> E[UI渲染]
  • JavaScript 引擎 :执行业务逻辑。
  • Bridge :负责 JS 与原生通信,异步执行。
  • 原生模块 :如 UI Manager、网络请求、存储等,调用原生 API。

虽然 Bridge 带来一定的性能损耗,但 React Native 通过 异步批处理机制 原生动画驱动 等方式优化性能瓶颈。

1.4 React Native 核心组件简介

React Native 提供了一系列核心 UI 组件,开发者可基于这些组件构建界面。

组件名 作用说明
View 布局容器,类似于 HTML 的 div
Text 显示文本内容
Image 显示图片资源
ScrollView 可滚动容器
TouchableOpacity 可点击的交互组件,用于按钮等场景

示例:构建一个简单的新闻列表项

import React from 'react';
import { View, Text, Image, TouchableOpacity, StyleSheet } from 'react-native';

const NewsItem = ({ title, imageUrl, onPress }) => {
  return (
    <TouchableOpacity style={styles.card} onPress={onPress}>
      <Image source={{ uri: imageUrl }} style={styles.image} />
      <Text style={styles.title}>{title}</Text>
    </TouchableOpacity>
  );
};

const styles = StyleSheet.create({
  card: {
    padding: 10,
    borderBottomWidth: 1,
    borderBottomColor: '#ccc',
  },
  image: {
    width: '100%',
    height: 200,
    resizeMode: 'cover',
  },
  title: {
    fontSize: 16,
    marginTop: 10,
  },
});

export default NewsItem;

这个组件定义了一个新闻卡片,包含图片和标题,并支持点击事件。通过 StyleSheet 定义样式,使组件具备良好的可维护性与样式隔离性。

说明:

  • TouchableOpacity :为组件添加点击反馈。
  • Image :通过 uri 加载远程图片资源。
  • StyleSheet :类似 CSS,但使用 JavaScript 对象定义。

通过组合这些基础组件,可以逐步构建出完整的新闻应用界面结构,为后续章节的功能开发打下坚实基础。

2. React组件在移动端的构建方式

在构建 React Native 应用时,组件是构建界面和逻辑的核心单元。React 的组件化思想使得开发者能够以模块化的方式构建复杂的 UI 结构,从而提高代码的可维护性、复用性与开发效率。本章将深入探讨 React 组件在移动端的构建方式,涵盖组件的基本结构、函数组件与类组件的对比、状态与生命周期管理、Hook API 的使用,以及在新闻应用中的组件拆分与通信实践。

2.1 组件化开发思想

组件化是 React 的核心理念之一,它鼓励开发者将 UI 拆分为独立、可复用的模块。每个组件都拥有自己的结构、行为和状态,这使得应用的开发和维护变得更加清晰和高效。

2.1.1 React组件的基本结构

React 组件可以看作是返回 JSX 的函数或类。它们通常包含以下部分:

  • 结构(UI) :通过 JSX 描述界面。
  • 行为(逻辑) :通过函数或类的方法实现交互逻辑。
  • 状态(State) :用于管理组件内部的动态数据。
  • 属性(Props) :用于接收外部传入的数据。
示例:一个简单的函数组件
import React from 'react';
import { View, Text, StyleSheet } from 'react-native';

const HelloWorld = () => {
  return (
    <View style={styles.container}>
      <Text style={styles.text}>Hello, React Native!</Text>
    </View>
  );
};

const styles = StyleSheet.create({
  container: {
    flex: 1,
    justifyContent: 'center',
    alignItems: 'center',
  },
  text: {
    fontSize: 20,
    fontWeight: 'bold',
  },
});

export default HelloWorld;
代码分析:
  • 导入模块 :引入 React 和基础 UI 组件 View Text
  • 函数组件定义 HelloWorld 是一个无状态组件,返回一个 JSX 结构。
  • 样式定义 :使用 StyleSheet 创建样式对象,提升性能并实现样式模块化。
  • 导出组件 :使用 export default 将组件暴露出去,供其他组件引用。

2.1.2 函数组件与类组件的对比

React 支持两种主要的组件类型:函数组件和类组件。它们在结构和使用方式上有显著差异。

特性 函数组件 类组件
定义方式 使用函数定义 使用 class 继承 React.Component
状态管理 需配合 Hook API 使用 state 使用 this.state setState()
生命周期方法 通过 useEffect 模拟 使用 componentDidMount
性能 更轻量,推荐使用 相对更重
可读性 更简洁,函数式风格 结构复杂,适合大型组件
可测试性 易于单元测试 需实例化,稍复杂
示例:类组件实现相同功能
import React from 'react';
import { View, Text, StyleSheet } from 'react-native';

class HelloWorldClass extends React.Component {
  render() {
    return (
      <View style={styles.container}>
        <Text style={styles.text}>Hello, React Native!</Text>
      </View>
    );
  }
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    justifyContent: 'center',
    alignItems: 'center',
  },
  text: {
    fontSize: 20,
    fontWeight: 'bold',
  },
});

export default HelloWorldClass;
代码分析:
  • 类组件定义 :继承 React.Component ,并通过 render() 方法返回 JSX。
  • 样式与结构 :与函数组件相同,保持一致性。
  • 生命周期 :如果需要添加生命周期逻辑,可以在类中添加如 componentDidMount() 等方法。

2.2 状态与生命周期管理

状态是组件中动态数据的核心,它决定了组件的行为和渲染内容。React 提供了两种状态管理方式:类组件的 state 和函数组件中使用 useState Hook。

2.2.1 State与Props的使用方式

  • State :用于组件内部的状态管理,变化会触发组件重新渲染。
  • Props :用于组件之间的数据传递,父组件通过 props 向子组件传值。
示例:带状态的函数组件
import React, { useState } from 'react';
import { View, Text, Button, StyleSheet } from 'react-native';

const Counter = () => {
  const [count, setCount] = useState(0);

  return (
    <View style={styles.container}>
      <Text style={styles.text}>点击次数: {count}</Text>
      <Button title="点击我" onPress={() => setCount(count + 1)} />
    </View>
  );
};

const styles = StyleSheet.create({
  container: {
    padding: 20,
    alignItems: 'center',
  },
  text: {
    fontSize: 18,
    marginBottom: 10,
  },
});

export default Counter;
代码分析:
  • 引入 useState :用于在函数组件中管理状态。
  • 状态初始化 :初始值为 0。
  • 更新状态 :当按钮被点击时,调用 setCount() 更新状态。
  • 响应式更新 :状态变化后,组件自动重新渲染。

2.2.2 类组件的生命周期方法

类组件通过生命周期方法控制组件的创建、更新和销毁过程,常见方法如下:

生命周期阶段 方法名 说明
挂载阶段 constructor() 初始化 state 和 props
componentDidMount() 组件挂载完成,适合发起网络请求
更新阶段 shouldComponentUpdate() 控制是否重新渲染
componentDidUpdate() 组件更新后执行
卸载阶段 componentWillUnmount() 清除定时器、取消订阅等资源释放
示例:类组件中的生命周期使用
import React from 'react';
import { Text, View } from 'react-native';

class LifecycleDemo extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      data: null,
    };
  }

  componentDidMount() {
    // 模拟网络请求
    setTimeout(() => {
      this.setState({ data: '数据加载完成' });
    }, 2000);
  }

  componentDidUpdate(prevProps, prevState) {
    if (prevState.data !== this.state.data) {
      console.log('数据更新了');
    }
  }

  componentWillUnmount() {
    console.log('组件即将卸载');
  }

  render() {
    return (
      <View>
        <Text>{this.state.data || '加载中...'}</Text>
      </View>
    );
  }
}

export default LifecycleDemo;
代码分析:
  • componentDidMount :模拟异步加载数据,2秒后更新状态。
  • componentDidUpdate :检测数据变化并输出日志。
  • componentWillUnmount :清理资源或取消异步操作。

2.2.3 Hook API在函数组件中的应用

React Hooks 是 React 16.8 引入的新特性,允许在函数组件中使用状态和生命周期等特性。

常见 Hook API:
Hook 用途
useState 管理状态
useEffect 模拟生命周期,执行副作用逻辑
useContext 获取上下文值
useRef 获取 DOM 引用或保存变量
useCallback 缓存函数,避免重复创建
useMemo 缓存计算结果,避免重复计算
示例:使用 useEffect 替代生命周期
import React, { useState, useEffect } from 'react';
import { Text, View } from 'react-native';

const HookLifecycle = () => {
  const [data, setData] = useState(null);

  useEffect(() => {
    // componentDidMount + componentDidUpdate
    const timer = setTimeout(() => {
      setData('数据加载完成');
    }, 2000);

    // componentWillUnmount
    return () => {
      clearTimeout(timer);
    };
  }, []); // 空数组表示只在挂载和卸载时执行

  return (
    <View>
      <Text>{data || '加载中...'}</Text>
    </View>
  );
};

export default HookLifecycle;
代码分析:
  • useEffect :代替 componentDidMount componentWillUnmount
  • 副作用清理 :返回一个函数用于清除副作用,如取消定时器。
  • 依赖数组 :空数组 [] 表示只在组件挂载时执行一次。

2.3 新闻应用中的组件拆分实践

在实际开发中,良好的组件拆分能够提升项目的可维护性和可复用性。在新闻应用中,常见的组件包括新闻卡片、头部组件、底部组件等。

2.3.1 构建新闻卡片组件

新闻卡片是新闻应用中最核心的 UI 组件之一,通常包含标题、图片、摘要等内容。

import React from 'react';
import { View, Text, Image, StyleSheet, TouchableOpacity } from 'react-native';

const NewsCard = ({ title, summary, imageUrl, onPress }) => {
  return (
    <TouchableOpacity style={styles.card} onPress={onPress}>
      <Image source={{ uri: imageUrl }} style={styles.image} />
      <View style={styles.content}>
        <Text style={styles.title}>{title}</Text>
        <Text style={styles.summary}>{summary}</Text>
      </View>
    </TouchableOpacity>
  );
};

const styles = StyleSheet.create({
  card: {
    backgroundColor: '#fff',
    borderRadius: 8,
    overflow: 'hidden',
    margin: 10,
    shadowColor: '#000',
    shadowOpacity: 0.1,
    shadowRadius: 5,
    elevation: 2,
  },
  image: {
    height: 200,
    width: '100%',
  },
  content: {
    padding: 10,
  },
  title: {
    fontSize: 18,
    fontWeight: 'bold',
  },
  summary: {
    fontSize: 14,
    color: '#666',
  },
});

export default NewsCard;
代码分析:
  • props :接收 title summary imageUrl onPress
  • 可点击区域 :使用 TouchableOpacity 实现卡片点击。
  • 样式设计 :采用圆角、阴影等提升视觉效果。

2.3.2 可复用的头部与底部组件设计

头部和底部通常在多个页面中复用,封装成独立组件有助于统一风格。

示例:通用头部组件
import React from 'react';
import { View, Text, StyleSheet } from 'react-native';

const Header = ({ title }) => {
  return (
    <View style={styles.header}>
      <Text style={styles.title}>{title}</Text>
    </View>
  );
};

const styles = StyleSheet.create({
  header: {
    backgroundColor: '#007AFF',
    paddingVertical: 15,
    alignItems: 'center',
  },
  title: {
    color: '#fff',
    fontSize: 20,
    fontWeight: 'bold',
  },
});

export default Header;

2.3.3 组件间通信与数据传递

组件间通信主要通过 props 实现。父组件通过 props 向子组件传递数据,子组件可通过回调函数向父组件反馈事件。

示例:父组件向子组件传值并监听点击事件
import React from 'react';
import { View } from 'react-native';
import NewsCard from './NewsCard';

const NewsList = () => {
  const newsItems = [
    {
      id: 1,
      title: 'React Native 101',
      summary: 'React Native 入门教程',
      imageUrl: 'https://example.com/image1.jpg',
    },
    {
      id: 2,
      title: 'Hooks 深度解析',
      summary: 'React Hook 使用详解',
      imageUrl: 'https://example.com/image2.jpg',
    },
  ];

  const handlePress = (id) => {
    console.log(`点击了新闻 ${id}`);
  };

  return (
    <View>
      {newsItems.map((item) => (
        <NewsCard
          key={item.id}
          title={item.title}
          summary={item.summary}
          imageUrl={item.imageUrl}
          onPress={() => handlePress(item.id)}
        />
      ))}
    </View>
  );
};

export default NewsList;
代码分析:
  • 数据映射 :使用 map() 遍历新闻列表,生成多个 NewsCard
  • 事件绑定 :每个卡片绑定点击事件并传入新闻 ID。
  • 父子通信 :子组件通过调用 onPress 回调将事件反馈给父组件。

本章通过函数组件与类组件的对比、状态与生命周期管理、Hook 的使用以及新闻应用的组件拆分与通信实践,全面阐述了 React 组件在移动端的构建方式。下一章将继续深入导航功能的实现,探讨如何在多页面之间进行跳转与数据传递。

3. 使用react-navigation实现多页面导航

在现代的移动应用开发中,页面之间的导航是构建用户体验的重要组成部分。React Native 本身并不提供原生的导航支持,但社区中广泛使用的 react-navigation 库为开发者提供了一套完整的导航解决方案。它支持栈式导航(Stack)、标签页导航(Tab)和抽屉导航(Drawer)等多种导航器类型,能够满足大多数应用的页面跳转与结构管理需求。

本章将从导航器的基本类型出发,深入讲解如何使用 react-navigation 实现多页面之间的跳转与参数传递,并结合新闻应用的实际场景,展示如何设计清晰、易维护的导航结构。

3.1 导航器的基本类型

react-navigation 提供了多种导航器类型,适用于不同的应用场景。最常见的三种导航器是 Stack Navigator(栈导航器)、Tab Navigator(标签页导航器)和 Drawer Navigator(抽屉导航器)。理解它们的使用方式和适用场景,是构建复杂导航结构的基础。

3.1.1 Stack Navigator与Tab Navigator的使用

Stack Navigator 是一种常见的页面导航结构,允许用户在多个页面之间以“堆栈”的方式跳转,后进先出(LIFO)。每个新页面都会被推入栈顶,用户点击返回时则从栈中弹出。

Tab Navigator 用于实现底部或顶部标签页切换功能,适合在几个固定页面之间快速切换,如新闻应用的“首页”、“分类”、“我的”等模块。

安装依赖

首先确保安装了 react-navigation 及其依赖:

npm install @react-navigation/native
npm install react-native-screens react-native-safe-area-context react-native-gesture-handler react-native-reanimated
npm install @react-navigation/stack
npm install @react-navigation/bottom-tabs
示例代码:Stack 与 Tab 导航器的简单使用
// App.js
import React from 'react';
import { NavigationContainer } from '@react-navigation/native';
import { createStackNavigator } from '@react-navigation/stack';
import { createBottomTabNavigator } from '@react-navigation/bottom-tabs';

const Stack = createStackNavigator();
const Tab = createBottomTabNavigator();

// 页面组件
function HomeScreen() {
  return <Text style={{ padding: 20 }}>首页内容</Text>;
}

function NewsDetailScreen({ route }) {
  const { title } = route.params;
  return <Text style={{ padding: 20 }}>新闻详情:{title}</Text>;
}

function CategoryScreen() {
  return <Text style={{ padding: 20 }}>分类内容</Text>;
}

function ProfileScreen() {
  return <Text style={{ padding: 20 }}>个人中心</Text>;
}

// 栈导航器
function NewsStack() {
  return (
    <Stack.Navigator>
      <Stack.Screen name="Home" component={HomeScreen} />
      <Stack.Screen name="NewsDetail" component={NewsDetailScreen} />
    </Stack.Navigator>
  );
}

// 标签页导航器
export default function App() {
  return (
    <NavigationContainer>
      <Tab.Navigator>
        <Tab.Screen name="新闻" component={NewsStack} />
        <Tab.Screen name="分类" component={CategoryScreen} />
        <Tab.Screen name="我的" component={ProfileScreen} />
      </Tab.Navigator>
    </NavigationContainer>
  );
}
代码分析
  • createStackNavigator() 创建了一个栈导航器,用于实现页面的跳转。
  • createBottomTabNavigator() 创建了一个底部标签导航器,包含三个页面:新闻、分类、我的。
  • NewsStack 是一个嵌套在 Tab 中的 Stack,允许在“新闻”标签页中跳转到新闻详情页。
  • route.params 用于接收从上一个页面传递过来的参数,例如新闻标题。

3.1.2 Drawer Navigator的配置方式

Drawer Navigator 提供了一个滑动抽屉式的菜单结构,常用于主菜单导航,例如侧边栏选项。在新闻应用中,抽屉菜单可以包含“设置”、“收藏”、“关于”等功能。

安装 Drawer 导航器依赖
npm install @react-navigation/drawer
示例代码:Drawer 导航器实现
// App.js
import { createDrawerNavigator } from '@react-navigation/drawer';

const Drawer = createDrawerNavigator();

function SettingsScreen() {
  return <Text style={{ padding: 20 }}>设置页面</Text>;
}

function FavoritesScreen() {
  return <Text style={{ padding: 20 }}>收藏页面</Text>;
}

function App() {
  return (
    <NavigationContainer>
      <Drawer.Navigator initialRouteName="新闻">
        <Drawer.Screen name="新闻" component={NewsStack} />
        <Drawer.Screen name="收藏" component={FavoritesScreen} />
        <Drawer.Screen name="设置" component={SettingsScreen} />
      </Drawer.Navigator>
    </NavigationContainer>
  );
}
代码分析
  • createDrawerNavigator() 创建了一个抽屉导航器。
  • Drawer.Screen 定义了抽屉菜单中的各个页面。
  • 可以将 NewsStack 嵌套在抽屉菜单中,实现主页面与子页面的层级关系。
Drawer 导航器的优缺点
优点 缺点
结构清晰,适合多层级菜单 占用屏幕空间较大
操作方式直观,符合用户习惯 移动端屏幕较小可能影响体验

3.2 导航传参与页面跳转

在实际应用中,页面之间往往需要传递数据,比如点击新闻列表项后跳转到对应的新闻详情页。 react-navigation 提供了灵活的传参机制和页面跳转 API。

3.2.1 页面之间参数传递的方法

通过 navigation.navigate 传参

在点击事件中,可以使用 navigation.navigate 方法跳转页面并携带参数。

// HomeScreen.js
function HomeScreen({ navigation }) {
  return (
    <TouchableOpacity
      onPress={() =>
        navigation.navigate('NewsDetail', {
          title: 'React Native 简介',
          id: 1001,
        })
      }
    >
      <Text>点击查看详情</Text>
    </TouchableOpacity>
  );
}

在目标页面中,通过 route.params 接收参数:

function NewsDetailScreen({ route }) {
  const { title, id } = route.params;
  return <Text>新闻标题:{title},ID:{id}</Text>;
}
通过 navigation.setParams 动态更新参数

如果需要在页面加载后动态更新参数,可以使用 navigation.setParams 方法:

useEffect(() => {
  navigation.setParams({ loaded: true });
}, [navigation]);

3.2.2 嵌套导航器的实现策略

在复杂应用中,常常需要嵌套多个导航器,比如 Tab 嵌套 Stack,或者 Drawer 嵌套 Tab。这种结构可以实现更丰富的页面层级。

示例:Tab 嵌套 Stack
<Tab.Navigator>
  <Tab.Screen name="新闻" component={NewsStack} />
  <Tab.Screen name="分类" component={CategoryStack} />
</Tab.Navigator>

其中 NewsStack CategoryStack 都是独立的栈导航器。

示例:Drawer 嵌套 Tab
<Drawer.Navigator>
  <Drawer.Screen name="主页" component={MainTabNavigator} />
  <Drawer.Screen name="设置" component={SettingsScreen} />
</Drawer.Navigator>

其中 MainTabNavigator 是一个包含多个 Tab 页面的导航器。

3.3 新闻应用中的导航结构设计

在新闻类应用中,导航结构的设计需要兼顾用户体验和代码的可维护性。通常包括首页、详情页、分类页、个人中心等页面,并通过 Tab 或 Drawer 进行组织。

3.3.1 首页与详情页的跳转逻辑

首页通常是一个新闻列表页,点击某条新闻后跳转到详情页,并携带新闻 ID 或标题等参数。

function NewsItem({ item, navigation }) {
  return (
    <TouchableOpacity
      onPress={() =>
        navigation.navigate('NewsDetail', {
          title: item.title,
          id: item.id,
        })
      }
    >
      <Text>{item.title}</Text>
    </TouchableOpacity>
  );
}

在详情页中接收参数并展示内容:

function NewsDetailScreen({ route }) {
  const { title, id } = route.params;
  // 通过 id 请求新闻详情数据
  return <Text>新闻标题:{title}</Text>;
}

3.3.2 使用Bottom Tab实现分类浏览

Bottom Tab 是新闻应用中最常见的导航结构之一,通常包含首页、分类、收藏、我的等页面。

<Tab.Navigator>
  <Tab.Screen name="首页" component={HomeScreen} />
  <Tab.Screen name="分类" component={CategoryScreen} />
  <Tab.Screen name="收藏" component={FavoritesScreen} />
  <Tab.Screen name="我的" component={ProfileScreen} />
</Tab.Navigator>
优化 Tab 导航器样式

可以通过 screenOptions 自定义 Tab 的图标、文字颜色、背景色等:

<Tab.Navigator
  screenOptions={({ route }) => ({
    tabBarIcon: ({ focused, color, size }) => {
      let iconName;
      if (route.name === '首页') {
        iconName = focused ? 'home' : 'home-outline';
      } else if (route.name === '分类') {
        iconName = focused ? 'list' : 'list-outline';
      }
      return <Ionicons name={iconName} size={size} color={color} />;
    },
  })}
  tabBarOptions={{
    activeTintColor: '#007AFF',
    inactiveTintColor: 'gray',
  }}
>
  {/* Tab.Screen */}
</Tab.Navigator>

3.3.3 导航栏的自定义与样式优化

react-navigation 提供了强大的自定义导航栏功能,可以通过 options 设置标题、按钮、背景色等。

自定义 Stack 页面的导航栏
<Stack.Navigator>
  <Stack.Screen
    name="Home"
    component={HomeScreen}
    options={{
      title: '新闻首页',
      headerStyle: {
        backgroundColor: '#007AFF',
      },
      headerTintColor: '#fff',
      headerTitleStyle: {
        fontWeight: 'bold',
      },
    }}
  />
</Stack.Navigator>
添加右上角按钮
<Stack.Screen
  name="NewsDetail"
  component={NewsDetailScreen}
  options={({ navigation }) => ({
    title: '新闻详情',
    headerRight: () => (
      <TouchableOpacity
        onPress={() => Alert.alert('分享')}
        style={{ marginRight: 10 }}
      >
        <Text style={{ color: '#fff' }}>分享</Text>
      </TouchableOpacity>
    ),
  })}
/>

总结性流程图:导航结构设计

graph TD
    A[新闻应用导航结构] --> B[Drawer Navigator]
    B --> C[Tab Navigator]
    C --> D[首页 Stack]
    D --> E[新闻列表]
    D --> F[新闻详情]
    C --> G[分类]
    C --> H[收藏]
    B --> I[设置]
    B --> J[关于]

通过本章内容,我们系统地学习了 react-navigation 的多种导航器类型、参数传递方式以及在新闻应用中的实际应用。这些知识将为后续章节中构建完整的新闻应用奠定坚实基础。

4. 利用FlatList高效展示新闻列表

在移动应用开发中,高效地展示大量数据是提升用户体验的关键。尤其是在新闻类应用中,列表展示是核心功能之一。React Native 提供了多种列表组件,其中 FlatList 是最常用于处理可滚动、可复用的长列表数据的组件。本章将深入探讨 FlatList 的使用方式、性能优化策略、数据动态加载机制,以及如何结合交互设计和样式优化,打造一个流畅、美观的新闻列表界面。

4.1 列表组件的选择与性能优化

在 React Native 中,列表展示通常有 ScrollView FlatList 两种选择。两者各有优劣,选择合适的组件对性能至关重要。

4.1.1 ScrollView 与 FlatList 的对比

特性 ScrollView FlatList
数据量支持 不适合大量数据 专为大量数据设计
渲染性能 所有子元素一次性渲染 按需渲染可见区域
内存占用
自定义能力 简单但缺乏优化机制 支持分页、下拉刷新、懒加载等高级功能
适用场景 数据量小、结构简单 列表数据量大、需要滚动交互
示例代码:使用 ScrollView 展示新闻列表
import React from 'react';
import { ScrollView, View, Text } from 'react-native';

const NewsListScrollView = ({ newsItems }) => {
  return (
    <ScrollView>
      {newsItems.map((item, index) => (
        <View key={index} style={{ padding: 10, borderBottomWidth: 1 }}>
          <Text>{item.title}</Text>
        </View>
      ))}
    </ScrollView>
  );
};

export default NewsListScrollView;

逻辑分析
- 使用 ScrollView 包裹多个 View 组件,逐一渲染所有新闻项。
- key 是 React 的重要机制,用于标识列表中每个元素的唯一性。
- 该方式在数据量小的情况下表现良好,但在数据量大时会导致性能下降,因为所有元素都会被一次性加载。

示例代码:使用 FlatList 展示新闻列表
import React from 'react';
import { FlatList, View, Text } from 'react-native';

const NewsListFlatList = ({ newsItems }) => {
  const renderItem = ({ item }) => (
    <View style={{ padding: 10, borderBottomWidth: 1 }}>
      <Text>{item.title}</Text>
    </View>
  );

  return (
    <FlatList
      data={newsItems}
      renderItem={renderItem}
      keyExtractor={(item, index) => index.toString()}
    />
  );
};

export default NewsListFlatList;

逻辑分析
- FlatList 接收 data 数组和 renderItem 函数,按需渲染当前可视区域内的项。
- keyExtractor 用于生成每一项的唯一标识符,通常使用 index 或数据中的唯一字段。
- 该组件只渲染当前可见区域内的元素,极大提升了性能。

4.1.2 FlatList 的渲染优化策略

为了进一步提升 FlatList 的性能,我们可以采用以下几种优化策略:

1. 使用 getItemLayout 提升滚动性能

当列表项高度固定时,使用 getItemLayout 可以避免动态计算高度,提升滚动流畅度。

<FlatList
  data={newsItems}
  renderItem={renderItem}
  keyExtractor={(item) => item.id.toString()}
  getItemLayout={(data, index) => (
    { length: 80, offset: 80 * index, index }
  )}
/>

参数说明
- length : 每个列表项的高度。
- offset : 当前项距离顶部的距离。
- index : 当前项索引。

2. 设置 initialNumToRender 限制初始渲染数量
<FlatList
  data={newsItems}
  renderItem={renderItem}
  keyExtractor={(item) => item.id.toString()}
  initialNumToRender={5}
/>

作用 :控制初始渲染的项数,减少首次加载时间。

3. 使用 windowSize 控制渲染窗口大小
<FlatList
  data={newsItems}
  renderItem={renderItem}
  keyExtractor={(item) => item.id.toString()}
  windowSize={5}
/>

作用 :控制可视区域外缓存的项数,平衡内存占用与流畅度。

4. 使用 removeClippedSubviews 提升内存效率(Android)
<FlatList
  data={newsItems}
  renderItem={renderItem}
  keyExtractor={(item) => item.id.toString()}
  removeClippedSubviews={true}
/>

作用 :移除不可见的视图子组件,减少内存占用。

4.2 列表数据的动态加载

新闻类应用通常不会一次性加载所有数据,而是采用分页加载或无限滚动的方式获取数据。这不仅节省了资源,也提升了用户体验。

4.2.1 分页加载与无限滚动实现

实现思路:
  • 当用户滚动到列表底部时,自动加载下一页数据。
  • 显示加载指示器,避免用户困惑。
  • 防止重复请求,使用节流或锁机制。
示例代码:实现无限滚动加载
import React, { useState, useEffect } from 'react';
import { FlatList, ActivityIndicator, View } from 'react-native';

const InfiniteScrollNewsList = () => {
  const [news, setNews] = useState([]);
  const [page, setPage] = useState(1);
  const [loading, setLoading] = useState(false);

  const loadMoreNews = async () => {
    if (loading) return;
    setLoading(true);
    try {
      const newItems = await fetchNews(page);
      setNews(prev => [...prev, ...newItems]);
      setPage(prev => prev + 1);
    } catch (error) {
      console.error(error);
    } finally {
      setLoading(false);
    }
  };

  useEffect(() => {
    loadMoreNews();
  }, []);

  const renderFooter = () => {
    if (!loading) return null;
    return (
      <View style={{ padding: 10 }}>
        <ActivityIndicator size="small" color="#000" />
      </View>
    );
  };

  return (
    <FlatList
      data={news}
      renderItem={({ item }) => (
        <View style={{ padding: 15 }}>
          <Text>{item.title}</Text>
        </View>
      )}
      keyExtractor={item => item.id.toString()}
      onEndReached={loadMoreNews}
      onEndReachedThreshold={0.5}
      ListFooterComponent={renderFooter}
    />
  );
};

// 模拟 API 请求
const fetchNews = async (page) => {
  return new Promise(resolve => {
    setTimeout(() => {
      const newItems = Array.from({ length: 10 }, (_, i) => ({
        id: page * 10 + i,
        title: `新闻标题 - 第 ${page * 10 + i} 条`
      }));
      resolve(newItems);
    }, 1000);
  });
};

export default InfiniteScrollNewsList;

逻辑分析
- 使用 useState 管理新闻数据、当前页码和加载状态。
- useEffect 在组件初次加载时调用首次数据加载。
- onEndReached onEndReachedThreshold 实现滚动到底部自动加载。
- ListFooterComponent 显示加载提示。
- 使用 loading 状态防止重复请求。

4.2.2 列表项点击事件与跳转处理

在新闻列表中,点击某一项应跳转到详情页。这需要结合 react-navigation 进行页面跳转。

示例代码:列表项点击跳转
import { useNavigation } from '@react-navigation/native';

const NewsItem = ({ item }) => {
  const navigation = useNavigation();

  const handlePress = () => {
    navigation.navigate('NewsDetail', { newsId: item.id });
  };

  return (
    <TouchableOpacity onPress={handlePress}>
      <View style={{ padding: 15 }}>
        <Text>{item.title}</Text>
      </View>
    </TouchableOpacity>
  );
};

逻辑分析
- 使用 useNavigation 获取导航对象。
- navigate 方法用于跳转到目标页面,并传递参数 newsId
- TouchableOpacity 提供点击反馈。

4.3 新闻列表的交互与样式设计

除了数据加载,新闻列表的交互和样式设计也是提升用户体验的重要环节。

4.3.1 列表项的动态高度与图片适配

在新闻列表中,图片和文字的排版通常不是固定高度。可以使用 Image 组件结合 onLoad 事件动态计算高度。

示例代码:动态高度适配图片
import React, { useState } from 'react';
import { Image, View, Text } from 'react-native';

const NewsCard = ({ item }) => {
  const [imageHeight, setImageHeight] = useState(150);

  const onImageLoad = ({ nativeEvent: { source: { height, width } } }) => {
    const aspectRatio = height / width;
    setImageHeight(200 * aspectRatio); // 根据容器宽度调整高度
  };

  return (
    <View style={{ padding: 10 }}>
      <Image
        source={{ uri: item.imageUrl }}
        style={{ width: '100%', height: imageHeight }}
        onLoad={onImageLoad}
      />
      <Text style={{ marginTop: 10 }}>{item.title}</Text>
    </View>
  );
};

逻辑分析
- 使用 onLoad 回调获取图片宽高,计算宽高比。
- 动态设置 imageHeight ,实现响应式图片布局。

4.3.2 下拉刷新与加载更多功能实现

结合 refreshing onRefresh 属性,可以轻松实现下拉刷新功能。

示例代码:下拉刷新 + 加载更多
<FlatList
  data={news}
  renderItem={({ item }) => <NewsItem item={item} />}
  keyExtractor={item => item.id.toString()}
  refreshing={refreshing}
  onRefresh={handleRefresh}
  onEndReached={loadMoreNews}
  onEndReachedThreshold={0.5}
  ListFooterComponent={renderFooter}
/>
const [refreshing, setRefreshing] = useState(false);

const handleRefresh = async () => {
  setRefreshing(true);
  try {
    const newItems = await fetchNews(1);
    setNews(newItems);
    setPage(2);
  } catch (error) {
    console.error(error);
  } finally {
    setRefreshing(false);
  }
};

逻辑分析
- refreshing 控制刷新状态。
- onRefresh 触发刷新操作,重新获取第一页数据。
- 结合 ActivityIndicator 提供用户反馈。

4.3.3 列表缓存与数据本地存储的结合

为了提升应用响应速度和离线体验,可以将新闻数据缓存到本地,例如使用 AsyncStorage Realm

示例代码:使用 AsyncStorage 缓存新闻数据
import AsyncStorage from '@react-native-async-storage/async-storage';

const loadCachedNews = async () => {
  try {
    const cached = await AsyncStorage.getItem('newsCache');
    if (cached) {
      setNews(JSON.parse(cached));
    }
  } catch (e) {
    console.error('加载缓存失败');
  }
};

const saveNewsToCache = async (data) => {
  try {
    await AsyncStorage.setItem('newsCache', JSON.stringify(data));
  } catch (e) {
    console.error('缓存失败');
  }
};

逻辑分析
- loadCachedNews 用于从本地读取缓存。
- saveNewsToCache 用于将新数据写入缓存。
- 可在应用启动时优先加载缓存,同时后台请求新数据更新。

总结

本章围绕 FlatList 的高效使用展开,从组件选择、性能优化、数据加载、交互设计到本地缓存策略,全面覆盖了新闻列表开发中的关键技术点。通过合理使用 FlatList 的特性,我们不仅能实现流畅的滚动体验,还能结合异步加载、下拉刷新等功能,打造出一个高性能、用户体验良好的新闻列表界面。

5. 使用StyleSheet与Dimensions实现响应式样式

响应式设计是现代移动应用开发中不可或缺的一环。在React Native中, StyleSheet Dimensions 是实现跨设备适配和动态布局的关键工具。本章将深入探讨如何利用 StyleSheet 定义高效的样式规则,结合 Dimensions 动态获取屏幕信息,构建在不同设备上都能良好展示的新闻应用界面。

5.1 样式表的定义与使用

React Native 提供了 StyleSheet API 来集中管理样式,这不仅提高了代码的可读性和维护性,还提升了渲染性能。通过 StyleSheet.create() 创建的样式对象会被 React Native 内部优化,从而实现更高效的样式计算和渲染。

5.1.1 StyleSheet对象的创建与引用

创建 StyleSheet 的方式如下:

import { StyleSheet } from 'react-native';

const styles = StyleSheet.create({
  container: {
    flex: 1,
    justifyContent: 'center',
    alignItems: 'center',
    padding: 16,
  },
  title: {
    fontSize: 24,
    fontWeight: 'bold',
    color: '#333',
  },
});

在组件中使用:

import React from 'react';
import { View, Text } from 'react-native';
import styles from './styles';

const HomeScreen = () => {
  return (
    <View style={styles.container}>
      <Text style={styles.title}>欢迎使用新闻应用</Text>
    </View>
  );
};

export default HomeScreen;
逻辑分析与参数说明:
  • flex: 1 :表示该容器占据整个父容器的空间。
  • justifyContent alignItems :用于控制子元素在主轴和交叉轴上的对齐方式。
  • fontSize color :定义文本的字体大小和颜色。
  • padding :设置容器内部的留白。

5.1.2 Flexbox布局在移动端的应用

Flexbox 是 React Native 中默认的布局模型,它非常适合构建响应式界面。其核心概念包括:

  • flexDirection :决定主轴方向(默认为 column )。
  • justifyContent :控制子元素在主轴上的对齐方式。
  • alignItems :控制子元素在交叉轴上的对齐方式。
  • flexWrap :是否允许子元素换行。
示例代码:
const flexStyles = StyleSheet.create({
  container: {
    flex: 1,
    flexDirection: 'row',
    justifyContent: 'space-between',
    alignItems: 'center',
    flexWrap: 'wrap',
  },
  box: {
    width: 100,
    height: 100,
    backgroundColor: '#4A90E2',
    margin: 10,
  },
});
使用:
<View style={flexStyles.container}>
  <View style={flexStyles.box} />
  <View style={flexStyles.box} />
</View>

5.2 屏幕适配与动态计算

在多设备环境下,静态的样式往往不能满足不同屏幕尺寸的需求。React Native 提供了 Dimensions API 来动态获取设备的屏幕信息,从而实现更灵活的布局控制。

5.2.1 Dimensions API获取屏幕信息

使用方式如下:

import { Dimensions } from 'react-native';

const { width, height } = Dimensions.get('window');

console.log(`屏幕宽度:${width}, 高度:${height}`);

你可以监听屏幕变化事件:

import { Dimensions, Platform } from 'react-native';

let subscription;

if (Platform.OS === 'ios' || Platform.OS === 'android') {
  subscription = Dimensions.addEventListener('change', ({ window }) => {
    console.log(`屏幕尺寸变化:${window.width} x ${window.height}`);
  });
}

// 在组件卸载时移除监听
// subscription.remove();
参数说明:
  • Dimensions.get('window') :获取当前窗口的尺寸信息。
  • Dimensions.get('screen') :获取设备屏幕的物理尺寸。
  • addEventListener :用于监听屏幕尺寸变化事件。

5.2.2 动态计算字体大小与边距

我们可以根据屏幕宽度动态调整字体大小,实现更一致的视觉体验。

import { Dimensions } from 'react-native';

const { width } = Dimensions.get('window');

const dynamicStyles = StyleSheet.create({
  dynamicText: {
    fontSize: width * 0.05, // 字体大小为屏幕宽度的5%
    marginHorizontal: width * 0.04, // 水平边距为屏幕宽度的4%
  },
});
使用:
<Text style={dynamicStyles.dynamicText}>
  这是一个根据屏幕宽度动态调整字体大小的文本。
</Text>
逻辑分析:
  • width * 0.05 :确保在不同设备上字体大小保持比例一致。
  • marginHorizontal :横向边距同样采用比例计算,提升适配性。

5.3 新闻应用的响应式界面设计

在新闻应用中,响应式设计尤为重要,因为用户可能在不同设备、不同屏幕方向下浏览内容。我们将通过具体案例展示如何结合 StyleSheet Dimensions 实现更智能的布局。

5.3.1 不同设备下的布局适配方案

我们可以根据屏幕宽度来决定布局结构,例如在小屏幕上使用单列布局,大屏幕上使用双列布局。

import { Dimensions } from 'react-native';

const { width } = Dimensions.get('window');

const isLargeScreen = width >= 768;

const newsCardStyles = StyleSheet.create({
  container: {
    flexDirection: isLargeScreen ? 'row' : 'column',
    flexWrap: isLargeScreen ? 'wrap' : 'nowrap',
    padding: 10,
  },
  card: {
    width: isLargeScreen ? width / 2 - 15 : width - 20,
    margin: 5,
    backgroundColor: '#fff',
    borderRadius: 8,
    shadowColor: '#000',
    shadowOpacity: 0.1,
    shadowRadius: 5,
    elevation: 2,
  },
});
使用:
<View style={newsCardStyles.container}>
  <View style={newsCardStyles.card} />
  <View style={newsCardStyles.card} />
</View>
流程图:适配逻辑流程
graph TD
  A[获取屏幕宽度] --> B{是否大于768px?}
  B -->|是| C[使用双列布局]
  B -->|否| D[使用单列布局]
  C --> E[设置flexDirection为row]
  D --> F[设置flexDirection为column]

5.3.2 暗黑模式与主题切换实现

React Native 支持系统级的暗黑模式识别,我们可以通过 Appearance 模块来实现自动切换,也可以手动实现主题切换。

import { Appearance, useColorScheme } from 'react-native';

// 自动检测系统主题
const App = () => {
  const colorScheme = useColorScheme(); // 'light' or 'dark'
  return (
    <View style={colorScheme === 'dark' ? darkStyles.container : lightStyles.container}>
      {/* 内容 */}
    </View>
  );
};

// 手动切换主题
const [isDarkMode, setIsDarkMode] = useState(false);

const toggleTheme = () => {
  setIsDarkMode(!isDarkMode);
};

const darkStyles = StyleSheet.create({
  container: { backgroundColor: '#121212', color: '#fff' },
});

const lightStyles = StyleSheet.create({
  container: { backgroundColor: '#fff', color: '#000' },
});
逻辑分析:
  • useColorScheme() :监听系统主题变化。
  • darkStyles lightStyles :分别定义暗色和亮色样式。
  • toggleTheme() :实现手动切换主题的功能。

5.3.3 自定义组件的样式封装与复用

为了提高代码复用率,我们可以将通用样式封装成可复用的组件。

// components/ThemedText.js
import React from 'react';
import { Text } from 'react-native';
import styles from './ThemedTextStyles';

const ThemedText = ({ children, style }) => {
  const colorScheme = useColorScheme();
  const currentStyle = colorScheme === 'dark' ? styles.darkText : styles.lightText;

  return <Text style={[currentStyle, style]}>{children}</Text>;
};

export default ThemedText;
样式文件:
// components/ThemedTextStyles.js
import { StyleSheet } from 'react-native';

export default StyleSheet.create({
  darkText: {
    color: '#fff',
  },
  lightText: {
    color: '#000',
  },
});
使用:
<ThemedText style={{ fontSize: 18 }}>这是一段自适应主题的文本</ThemedText>
逻辑分析:
  • ThemedText 组件根据系统主题自动应用样式。
  • 支持通过 style 属性传入自定义样式,保持灵活性。
  • 适用于新闻应用中所有文本内容,提升开发效率。

通过本章的学习,我们掌握了如何使用 StyleSheet 构建高性能样式,结合 Dimensions 实现屏幕适配,并通过主题切换与组件封装提升应用的响应式能力。这些技术将在新闻应用的开发中发挥重要作用,为用户提供一致且流畅的交互体验。

6. 新闻数据的网络请求与异步加载(如axios)

在现代移动端应用开发中,数据的获取与处理是构建新闻类应用的关键环节。React Native 提供了多种方式进行网络请求,其中使用 axios 是一种非常流行且功能强大的方式。本章将深入讲解如何通过 axios 实现新闻数据的异步加载、状态管理与接口封装,帮助开发者构建更加稳定、可维护的新闻应用。

6.1 网络请求基础知识

6.1.1 HTTP协议与RESTful API调用

HTTP(HyperText Transfer Protocol)是客户端与服务器之间通信的基础协议。RESTful API 是一种基于 HTTP 的接口设计风格,具有无状态、统一接口等特点,广泛应用于前后端分离架构中。

在新闻应用中,我们通常会调用 RESTful 风格的 API 来获取新闻列表、新闻详情、分类数据等信息。

示例 API 请求结构:

GET https://api.example.com/news?page=1&limit=20

6.1.2 Fetch API 与 Axios 的对比

React Native 原生支持 fetch 方法进行网络请求,但 axios 在功能和易用性上更胜一筹。

特性 Fetch API Axios
自动转换 JSON
请求拦截
响应拦截
取消请求 需手动实现 支持 CancelToken
默认不带 cookie 可配置 withCredentials
浏览器兼容性 原生支持 需引入包

因此,在新闻应用中推荐使用 axios 来处理网络请求。

6.2 异步数据加载与状态管理

6.2.1 使用 async/await 处理异步请求

在 React 中,使用 async/await 是处理异步操作的推荐方式。我们可以在组件的生命周期(如 useEffect )中发起请求,获取新闻数据。

import axios from 'axios';

const fetchNews = async (page = 1) => {
  try {
    const response = await axios.get(`https://api.example.com/news?page=${page}&limit=20`);
    return response.data;
  } catch (error) {
    console.error('请求失败:', error);
    return [];
  }
};
  • axios.get(url) :发起 GET 请求。
  • try/catch :捕获异常,避免程序崩溃。
  • response.data :返回接口中的数据部分。

6.2.2 数据加载状态的 UI 反馈设计

在加载数据时,良好的用户反馈体验是必不可少的。我们可以使用状态变量来控制 UI 显示:

const [newsList, setNewsList] = useState([]);
const [loading, setLoading] = useState(true);
const [page, setPage] = useState(1);

useEffect(() => {
  const loadNews = async () => {
    setLoading(true);
    const data = await fetchNews(page);
    setNewsList(prev => [...prev, ...data]);
    setLoading(false);
  };

  loadNews();
}, [page]);

// 在组件中使用 loading 状态显示 LoadingIndicator
{loading && <ActivityIndicator size="large" color="#0000ff" />}
  • loading :控制是否显示加载动画。
  • ActivityIndicator :React Native 提供的加载组件。

6.3 新闻应用的数据接口集成实践

6.3.1 接口封装与统一请求管理

为了提高代码的可维护性和复用性,建议将所有网络请求集中管理。我们可以创建一个 api.js 文件来封装接口。

// src/api.js
import axios from 'axios';

const apiClient = axios.create({
  baseURL: 'https://api.example.com',
  timeout: 10000,
});

export const getNewsList = async (page = 1, limit = 20) => {
  try {
    const response = await apiClient.get(`/news?page=${page}&limit=${limit}`);
    return response.data;
  } catch (error) {
    console.error('获取新闻失败:', error.message);
    return [];
  }
};

export const getNewsDetail = async (id) => {
  try {
    const response = await apiClient.get(`/news/${id}`);
    return response.data;
  } catch (error) {
    console.error(`获取新闻详情失败(ID: ${id}):`, error.message);
    return null;
  }
};
  • baseURL :设置请求基础路径。
  • timeout :设置请求超时时间。
  • 每个接口方法统一返回 data ,便于组件中处理。

6.3.2 数据缓存与本地优先策略

为了提升用户体验,我们可以使用本地缓存策略,在网络请求前先尝试从本地读取数据。例如,使用 AsyncStorage react-native-sqlite-storage 存储最近获取的新闻列表。

import AsyncStorage from '@react-native-async-storage/async-storage';

const getNewsListWithCache = async (page = 1) => {
  const cacheKey = `news_page_${page}`;
  try {
    const cached = await AsyncStorage.getItem(cacheKey);
    if (cached) {
      return JSON.parse(cached);
    }

    const data = await getNewsList(page);
    await AsyncStorage.setItem(cacheKey, JSON.stringify(data));
    return data;
  } catch (error) {
    console.error('缓存失败:', error);
    return [];
  }
};
  • AsyncStorage.getItem() :读取缓存。
  • JSON.stringify(data) :将对象转为字符串存储。
  • JSON.parse(cached) :将字符串转回对象。

6.3.3 网络错误处理与重试机制

在实际开发中,网络请求可能因各种原因失败,如无网络、超时等。我们可以通过 axios-retry 插件实现自动重试机制。

npm install axios-retry
// src/api.js
import axios from 'axios';
import axiosRetry from 'axios-retry';

const apiClient = axios.create({
  baseURL: 'https://api.example.com',
  timeout: 10000,
});

axiosRetry(apiClient, {
  retries: 3,
  retryDelay: (retryCount) => {
    console.log(`第 ${retryCount} 次重试`);
    return retryCount * 1000; // 1s, 2s, 3s...
  },
  retryCondition: (error) => {
    return axiosRetry.isNetworkOrIdempotentRequestError(error);
  },
});
  • retries :最大重试次数。
  • retryDelay :每次重试的间隔时间。
  • retryCondition :定义哪些错误触发重试。

下一章我们将深入探讨如何利用 Redux 或 Context API 实现新闻应用的状态管理与全局数据共享。

本文还有配套的精品资源,点击获取 menu-r.4af5f7ec.gif

简介:React Native是由Facebook推出的开源框架,允许开发者使用JavaScript和React构建原生移动应用。本示例提供一个功能相对完整的新闻发布类型应用,涵盖React Native的核心概念与开发流程。内容包括UI组件构建、导航实现、样式设计、数据获取与状态管理、错误处理、第三方库集成及应用打包发布等模块,适合开发者深入学习并掌握React Native在实际项目中的应用技巧。


本文还有配套的精品资源,点击获取
menu-r.4af5f7ec.gif

更多推荐