React Native 全栈开发实战班 - 网络与数据之网络请求基础

在移动应用中,网络请求 是实现与服务器进行数据交互的核心功能。React Native 基于 JavaScript 的特性,提供了多种方式进行网络请求,包括使用 fetch API、axios 库以及 WebSocket 等。本章节将详细介绍如何在 React Native 中进行网络请求,包括基本用法、错误处理、请求拦截以及使用第三方库进行更复杂的网络操作。


1.1 网络请求概述

在 React Native 应用中,网络请求主要用于以下场景:

  • 数据获取: 从服务器获取数据,如用户信息、文章列表等。
  • 数据提交: 向服务器提交数据,如用户注册、登录、发布文章等。
  • 实时通信: 通过 WebSocket 实现实时数据推送,如聊天应用、实时通知等。

React Native 提供了多种方式进行网络请求:

  1. fetch API: 内置于 JavaScript 的网络请求 API,简单易用。
  2. axios 库: 第三方网络请求库,功能更强大,支持拦截器、取消请求等。
  3. WebSocket: 用于实现实时双向通信。

本章节将重点介绍 fetch API 和 axios 库的使用。


1.2 使用 fetch API

fetch 是 JavaScript 提供的一个用于进行网络请求的 API,React Native 对其进行了支持。

1.2.1 基本用法

语法:

javascript 复制代码
fetch(url, {
  method: 'GET', // 请求方法:GET, POST, PUT, DELETE, etc.
  headers: {
    'Content-Type': 'application/json',
    // 其他头部信息
  },
  body: JSON.stringify(data), // 请求体
})
  .then((response) => response.json())
  .then((json) => {
    // 处理响应数据
  })
  .catch((error) => {
    // 处理错误
  });

示例:GET 请求

javascript 复制代码
import React, { useEffect, useState } from 'react';
import { View, Text, StyleSheet } from 'react-native';

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

  useEffect(() => {
    fetch('https://jsonplaceholder.typicode.com/posts/1')
      .then((response) => response.json())
      .then((json) => setData(json))
      .catch((error) => console.error(error));
  }, []);

  return (
    <View style={styles.container}>
      {data ? (
        <Text style={styles.text}>{JSON.stringify(data)}</Text>
      ) : (
        <Text>Loading...</Text>
      )}
    </View>
  );
};

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

export default DataFetcher;

示例:POST 请求

javascript 复制代码
import React, { useState } from 'react';
import { View, Text, Button, StyleSheet } from 'react-native';

const DataPoster = () => {
  const [response, setResponse] = useState(null);

  const postData = () => {
    const data = { title: 'foo', body: 'bar', userId: 1 };

    fetch('https://jsonplaceholder.typicode.com/posts', {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json',
      },
      body: JSON.stringify(data),
    })
      .then((response) => response.json())
      .then((json) => setResponse(json))
      .catch((error) => console.error(error));
  };

  return (
    <View style={styles.container}>
      <Button title="Post Data" onPress={postData} />
      {response && <Text style={styles.text}>{JSON.stringify(response)}</Text>}
    </View>
  );
};

const styles = StyleSheet.create({
  container: {
    flex: 1,
    justifyContent: 'center',
    alignItems: 'center',
  },
  text: {
    fontSize: 16,
    marginTop: 10,
  },
});

export default DataPoster;
1.2.2 错误处理

在网络请求中,错误处理是非常重要的。可以通过 catch 捕获错误,并进行相应的处理。

示例:

javascript 复制代码
import React, { useEffect, useState } from 'react';
import { View, Text, StyleSheet } from 'react-native';

const ErrorHandlingExample = () => {
  const [error, setError] = useState(null);

  useEffect(() => {
    fetch('https://invalid-url.com/data')
      .then((response) => response.json())
      .then((json) => {
        // 处理数据
      })
      .catch((error) => {
        console.error(error);
        setError('网络请求失败');
      });
  }, []);

  return (
    <View style={styles.container}>
      {error && <Text style={styles.text}>{error}</Text>}
    </View>
  );
};

const styles = StyleSheet.create({
  container: {
    flex: 1,
    justifyContent: 'center',
    alignItems: 'center',
  },
  text: {
    fontSize: 16,
    color: 'red',
  },
});

export default ErrorHandlingExample;
1.2.3 请求拦截

fetch 本身不支持请求拦截,但可以通过封装 fetch 函数来实现。

示例:

javascript 复制代码
// api.js
import { Platform } from 'react-native';

const api = {
  get: (url, headers = {}) => {
    return fetch(url, {
      method: 'GET',
      headers: {
        'Content-Type': 'application/json',
        ...headers,
      },
    });
  },
  post: (url, data, headers = {}) => {
    return fetch(url, {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json',
        ...headers,
      },
      body: JSON.stringify(data),
    });
  },
  // 其他方法:put, delete, etc.
};

// 添加请求拦截器
api.interceptors = {
  request: {
    use: (callback) => {
      const originalGet = api.get;
      api.get = (url, headers) => {
        return callback(originalGet(url, headers));
      };

      const originalPost = api.post;
      api.post = (url, data, headers) => {
        return callback(originalPost(url, data, headers));
      };
      // 其他方法
    },
  },
};

export default api;
javascript 复制代码
// App.js
import React from 'react';
import { View, Text, StyleSheet } from 'react-native';
import api from './api';

api.interceptors.request.use((originalFetch) => (...args) => {
  // 添加请求头
  const [url, options] = args;
  options.headers = {
    ...options.headers,
    Authorization: 'Bearer token',
  };
  return originalFetch(url, options);
});

const App = () => {
  const fetchData = async () => {
    try {
      const response = await api.get('https://jsonplaceholder.typicode.com/posts/1');
      const json = await response.json();
      console.log(json);
    } catch (error) {
      console.error(error);
    }
  };

  return (
    <View style={styles.container}>
      <Text style={styles.text}>Fetch Data</Text>
      <Button title="Get Data" onPress={fetchData} />
    </View>
  );
};

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

export default App;

1.3 使用 axios

axios 是一个第三方网络请求库,功能更强大,支持拦截器、取消请求、请求超时等。相比 fetchaxios 提供了更简洁的 API 和更丰富的功能。

1.3.1 安装 axios
bash 复制代码
npm install axios
1.3.2 基本用法

以下是一个使用 axios 发送 POST 请求的示例:

javascript 复制代码
// components/PostData.js
import React, { useState } from 'react';
import { View, Text, Button, StyleSheet, ActivityIndicator } from 'react-native';
import axios from 'axios';

const PostData = () => {
  const [response, setResponse] = useState(null);
  const [loading, setLoading] = useState(false);

  const handlePost = async () => {
    setLoading(true);
    try {
      const data = { title: 'foo', body: 'bar', userId: 1 };
      const res = await axios.post('https://jsonplaceholder.typicode.com/posts', data);
      setResponse(res.data);
    } catch (error) {
      console.error(error);
      alert('请求失败');
    } finally {
      setLoading(false);
    }
  };

  return (
    <View style={styles.container}>
      <Button title="Post Data" onPress={handlePost} />
      {loading && <ActivityIndicator size="large" color="#0000ff" />}
      {response && (
        <View style={styles.responseContainer}>
          <Text style={styles.responseText}>Response:</Text>
          <Text>{JSON.stringify(response)}</Text>
        </View>
      )}
    </View>
  );
};

const styles = StyleSheet.create({
  container: {
    flex: 1,
    justifyContent: 'center',
    alignItems: 'center',
    padding: 20,
  },
  responseContainer: {
    marginTop: 20,
    padding: 10,
    backgroundColor: '#f0f0f0',
    borderRadius: 5,
  },
  responseText: {
    fontSize: 16,
    fontWeight: 'bold',
    marginBottom: 5,
  },
});

export default PostData;

解释:

  • 发送 POST 请求:

    • 使用 axios.post 方法发送 POST 请求,第一个参数是请求的 URL,第二个参数是请求体数据。
    • axios.post 返回一个 Promise,可以通过 thencatch 处理响应和错误。
  • 错误处理:

    • 使用 try...catch 捕获请求错误,并进行相应处理(如显示错误提示)。
  • 加载状态:

    • 使用 loading 状态控制 ActivityIndicator 的显示,提示用户请求正在进行中。
  • 显示响应数据:

    • 将响应数据存储在 response 状态中,并在界面上显示。
1.3.3 拦截器

axios 提供了请求拦截器和响应拦截器,可以在请求发送前和响应返回后进行统一处理。

示例:添加请求头和响应处理

javascript 复制代码
// api.js
import axios from 'axios';

// 创建 axios 实例
const api = axios.create({
  baseURL: 'https://jsonplaceholder.typicode.com',
});

// 添加请求拦截器
api.interceptors.request.use(
  (config) => {
    // 在发送请求之前做些什么
    config.headers['Authorization'] = 'Bearer token';
    return config;
  },
  (error) => {
    // 对请求错误做些什么
    return Promise.reject(error);
  }
);

// 添加响应拦截器
api.interceptors.response.use(
  (response) => {
    // 对响应数据做点什么
    return response;
  },
  (error) => {
    // 对响应错误做点什么
    return Promise.reject(error);
  }
);

export default api;
javascript 复制代码
// components/PostData.js
import React, { useState } from 'react';
import { View, Text, Button, StyleSheet, ActivityIndicator } from 'react-native';
import api from '../api';

const PostData = () => {
  const [response, setResponse] = useState(null);
  const [loading, setLoading] = useState(false);

  const handlePost = async () => {
    setLoading(true);
    try {
      const data = { title: 'foo', body: 'bar', userId: 1 };
      const res = await api.post('/posts', data);
      setResponse(res.data);
    } catch (error) {
      console.error(error);
      alert('请求失败');
    } finally {
      setLoading(false);
    }
  };

  return (
    <View style={styles.container}>
      <Button title="Post Data" onPress={handlePost} />
      {loading && <ActivityIndicator size="large" color="#0000ff" />}
      {response && (
        <View style={styles.responseContainer}>
          <Text style={styles.responseText}>Response:</Text>
          <Text>{JSON.stringify(response)}</Text>
        </View>
      )}
    </View>
  );
};

const styles = StyleSheet.create({
  container: {
    flex: 1,
    justifyContent: 'center',
    alignItems: 'center',
    padding: 20,
  },
  responseContainer: {
    marginTop: 20,
    padding: 10,
    backgroundColor: '#f0f0f0',
    borderRadius: 5,
  },
  responseText: {
    fontSize: 16,
    fontWeight: 'bold',
    marginBottom: 5,
  },
});

export default PostData;

解释:

  • 创建 axios 实例:

    • 使用 axios.create 创建一个 axios 实例,并设置 baseURL
  • 请求拦截器:

    • 在请求发送前添加 Authorization 请求头。
  • 响应拦截器:

    • 在响应返回后进行统一处理,例如处理错误码、格式化数据等。
  • 使用 axios 实例:

    • 在组件中使用 api.post 发送请求,无需重复添加请求头。
1.3.4 取消请求

axios 支持取消请求,可以通过 CancelToken 实现。

示例:

javascript 复制代码
// components/CancelablePost.js
import React, { useState } from 'react';
import { View, Text, Button, StyleSheet, ActivityIndicator } from 'react-native';
import axios from 'axios';

const CancelablePost = () => {
  const [response, setResponse] = useState(null);
  const [loading, setLoading] = useState(false);
  let cancelToken;

  const handlePost = async () => {
    setLoading(true);
    cancelToken = axios.CancelToken.source();
    try {
      const data = { title: 'foo', body: 'bar', userId: 1 };
      const res = await axios.post('https://jsonplaceholder.typicode.com/posts', data, {
        cancelToken: cancelToken.token,
      });
      setResponse(res.data);
    } catch (error) {
      if (axios.isCancel(error)) {
        console.log('请求取消');
      } else {
        console.error(error);
        alert('请求失败');
      }
    } finally {
      setLoading(false);
    }
  };

  const handleCancel = () => {
    if (cancelToken) {
      cancelToken.cancel('用户取消请求');
    }
  };

  return (
    <View style={styles.container}>
      <Button title="Post Data" onPress={handlePost} />
      <Button title="Cancel Request" onPress={handleCancel} />
      {loading && <ActivityIndicator size="large" color="#0000ff" />}
      {response && (
        <View style={styles.responseContainer}>
          <Text style={styles.responseText}>Response:</Text>
          <Text>{JSON.stringify(response)}</Text>
        </View>
      )}
    </View>
  );
};

const styles = StyleSheet.create({
  container: {
    flex: 1,
    justifyContent: 'center',
    alignItems: 'center',
    padding: 20,
  },
  responseContainer: {
    marginTop: 20,
    padding: 10,
    backgroundColor: '#f0f0f0',
    borderRadius: 5,
  },
  responseText: {
    fontSize: 16,
    fontWeight: 'bold',
    marginBottom: 5,
  },
});

export default CancelablePost;

解释:

  • 取消请求:
    • 使用 CancelToken.source() 创建一个取消令牌。
    • 在发送请求时,将取消令牌传递给 axios.post
    • 通过调用 cancelToken.cancel('用户取消请求') 可以取消请求。

作者简介

前腾讯电子签的前端负责人,现 whentimes tech CTO,专注于前端技术的大咖一枚!一路走来,从小屏到大屏,从 Web 到移动,什么前端难题都见过。热衷于用技术打磨产品,带领团队把复杂的事情做到极简,体验做到极致。喜欢探索新技术,也爱分享一些实战经验,帮助大家少走弯路!

温馨提示:可搜老码小张公号联系导师

相关推荐
jt君424265 天前
React Native JSI 深入剖析 — 第 7 部分中文技术整理:把 C++ 能力接到 iOS 和 Android
react native
jt君424265 天前
React Native JSI 深入剖析 — 第 6 部分中文技术整理:跨 JS 与 C++ 两个世界的内存所有权
react native
jt君424267 天前
React Native JSI 深入剖析 — 第 5 部分中文技术整理:用 HostObject 把 C++ 类暴露给 JavaScript
前端·react native
两个人的幸福7 天前
Windows 桌面应用自研 PHP 队列(下):完整代码与六大工程化优化
php
BingoGo9 天前
PHP 泛型之殇 泛型 RFC 提案被拒绝
后端·php
JaguarJack9 天前
PHP 泛型之殇 泛型 RFC 提案被拒绝
后端·php
用户30745969820710 天前
PHP 扩展——从入门到理解
php
鹏仔先生10 天前
拷贝漫画APP下载页PHP程序,后台带免费AI写作
php
网络研究院10 天前
2026年网络安全
网络·安全·法律·法规·趋势·发展
酣大智10 天前
ARP代理--工作原理
运维·网络·arp·arp代理