×

React Native里怎么用Axios发请求?从基础到实战全解答

作者:Terry2025.12.12来源:Web前端之家浏览:30评论:0
关键词:React Native Axios

React

做React Native开发时,网络请求是绕不开的环节——不管是拉取商品列表、提交用户信息,还是同步数据,都得和后端接口打交道,Axios作为当下流行的HTTP客户端,在Web端和React Native里都很常用,但刚接触RN的同学,常会纠结“咋在RN里用Axios发请求?配置、拦截、报错处理这些咋搞?”今天就从基础到实战,把Axios在React Native里的用法拆明白,解决你开发里的痛点~

Axios是啥?在React Native里为啥选它?

Axios是基于Promise的HTTP客户端,能在浏览器、Node.js(React Native也适用)环境发请求,RN本身有内置的fetch API,选Axios主要因为这些优势:

  • API更简洁fetch需要手动解析JSON(res.json())、自己写超时逻辑;Axios自动把响应转JSON,还能直接配置超时时间。

  • 拦截器省代码:能在“请求发出去前”“响应回来后”统一处理逻辑(比如加token、处理通用错误),项目里重复代码能少一大半。

  • 错误处理更直观:Axios把网络错误、状态码错误(如404、500)都封装成Promise的reject,配合try/catch.catch()很顺手;fetch得自己判断status是否成功。

  • 取消请求更方便:用AbortController或Axios自带的取消令牌,能轻松终止重复请求,避免性能问题。

举个简单对比,用fetch发GET请求得这么写:

fetch('https://api.example.com/data')
  .then(res => {
    if (!res.ok) throw new Error('请求失败');
    return res.json();
  })
  .then(data => console.log(data))
  .catch(err => console.error(err));

而Axios一行代码更简洁:

axios.get('https://api.example.com/data')
  .then(res => console.log(res.data))
  .catch(err => console.error(err));

能看出Axios把很多繁琐步骤封装了,开发效率更高。

怎么在React Native项目里引入Axios?

分两步完成安装和基础配置:

第一步:安装Axios依赖

打开终端,进入RN项目根目录,用npm或yarn安装:

# npm
npm install axios --save
# yarn
yarn add axios

第二步:在代码里引入并配置基础项

在需要发请求的文件里导入Axios:

import axios from 'axios';

如果项目里所有请求都要同一个基础地址(baseURL)、超时时间,建议创建自定义Axios实例(避免重复写配置),比如新建api.js

import axios from 'axios';
// 创建自定义实例,配置通用参数
const instance = axios.create({
  baseURL: 'https://your-api-domain.com/api/', // 后端接口基础地址
  timeout: 10000, // 超时时间(毫秒)
  headers: {
    'Content-Type': 'application/json', // 默认请求头
    // 也可以加通用Authorization(但登录前可能没token,后续用拦截器更灵活)
  }
});
export default instance;

之后在组件里用这个实例发请求,路径会自动拼接baseURL

import api from './api'; // 导入封装好的实例
const fetchData = () => {
  api.get('/user/list') // 实际请求地址:https://your-api-domain.com/api/user/list
    .then(res => { /* 处理数据 */ })
    .catch(err => { /* 处理错误 */ });
};

常用的请求方法咋写?(GET/POST等)

不同请求场景(查数据、提交数据)对应不同方法,逐个拆解:

GET请求:获取数据

场景1:带查询参数(?page=1&size=10
把参数放params里,Axios会自动拼到URL后:

// 示例:获取用户列表(带分页参数)
api.get('/user/list', {
  params: {
    page: 1,
    size: 10
  }
})
.then(res => console.log(res.data))
.catch(err => console.error('获取列表失败:', err));

场景2:路径参数(/user/{id}
如果接口是/user/123这种形式,直接用模板字符串拼路径:

const userId = 123;
api.get(`/user/${userId}`)
  .then(res => { /* 处理单个用户数据 */ });

POST请求:提交/新增数据

场景1:发送JSON数据
后端需JSON格式时,直接把数据放data里(Axios自动设Content-Type: application/json):

// 示例:用户注册(提交账号密码)
const userInfo = { username: 'test', password: '123456' };
api.post('/user/register', userInfo)
  .then(res => console.log('注册成功,返回:', res.data))
  .catch(err => console.error('注册失败:', err.response?.data || err.message));

场景2:发送表单数据(Form Data
若后端需multipart/form-data(比如上传文件),手动创建FormData

import { FormData } from 'react-native'; // RN的FormData
const uploadAvatar = () => {
  const formData = new FormData();
  formData.append('file', {
    uri: 'file:///path/to/avatar.jpg', // 文件本地路径
    name: 'avatar.jpg',
    type: 'image/jpeg'
  });
  formData.append('userId', '123'); // 其他表单字段
  api.post('/upload/avatar', formData, {
    headers: { 'Content-Type': 'multipart/form-data' } // 手动设请求头
  })
  .then(res => console.log('上传成功,新地址:', res.data.url))
  .catch(err => console.error('上传失败:', err));
};

PUT/PATCH/DELETE请求

这几个方法用法和POST类似,根据后端RESTful风格选:

  • PUT:全量更新资源(如替换整个用户信息)

  • PATCH:局部更新(如只改用户昵称)

  • DELETE:删除资源

示例(PATCH更新用户昵称):

const updateNickname = () => {
  const newNickname = { nickname: '新昵称' };
  api.patch(`/user/${userId}`, newNickname)
    .then(res => console.log('昵称更新成功', res.data))
    .catch(err => { /* 处理错误 */ });
};

拦截器有啥用?怎么给请求加统一处理?

拦截器是Axios的“核心优势”——能在请求发出去前响应回来后插入逻辑,减少重复代码。

请求拦截器:给所有请求加token、统一header

项目里登录后需带token?在请求拦截器里统一加:

// 回到封装的api.js,给instance加拦截器
instance.interceptors.request.use(
  config => {
    // 从本地取token(假设用AsyncStorage存储)
    const token = AsyncStorage.getItem('token'); 
    if (token) {
      config.headers.Authorization = `Bearer ${token}`; // token加到请求头
    }
    return config; // 必须返回config,否则请求发不出去
  },
  error => Promise.reject(error) // 请求前出错,直接抛错
);

这样所有用instance的请求,都会自动带token,不用每个请求写headers

响应拦截器:处理通用错误、数据格式化

后端返回通常有统一格式(如{ code, msg, data }),用响应拦截器统一处理:

instance.interceptors.response.use(
  response => {
    // 假设后端约定code=200为成功
    if (response.data.code !== 200) {
      // 业务错误抛给catch处理
      return Promise.reject(new Error(response.data.msg || '业务请求失败'));
    }
    return response.data.data; // 直接返回实际业务数据,简化后续调用
  },
  error => {
    // 处理网络/状态码错误
    if (error.response) {
      // 服务器返回错误(状态码非2xx)
      console.error('响应错误,状态码:', error.response.status);
      console.error('错误信息:', error.response.data);
    } else if (error.request) {
      // 请求发了但没响应(超时、断网)
      console.error('请求超时或无响应:', error.request);
    } else {
      // 请求配置错误
      console.error('请求配置错误:', error.message);
    }
    return Promise.reject(error); // 错误抛给业务代码
  }
);

配置后,业务代码调用接口时,直接拿到response.data.data(实际数据);只要code不对,会直接进catch,不用每个请求判断code,效率翻倍~

网络请求出错了咋处理?

Axios的错误分三类,针对性处理更高效:

情况1:网络错误(没网、超时)

用户断网或请求超时(配置了timeout但后端没响应)时,error.request有信息,error.responseundefined

业务代码里判断:

api.get('/data')
  .then(data => { /* 成功 */ })
  .catch(err => {
    if (err.request) {
      alert('网络不给力,请检查连接~');
    } else {
      alert('请求出错:' + err.message);
    }
  });

情况2:状态码错误(404、500等)

后端返回状态码非2xx(如401未授权、404资源不存在),error.response存在,含statusdata等信息。

可在响应拦截器或业务代码里根据status提示:

.catch(err => {
  if (err.response) {
    const status = err.response.status;
    if (status === 401) {
      alert('登录过期,请重新登录~');
      // 跳转到登录页等逻辑
    } else if (status === 404) {
      alert('请求的资源不存在~');
    } else {
      alert('服务器出错了,请稍后再试~');
    }
  }
});

情况3:业务错误(code≠200

后端用code表示业务状态(如code=4001代表“用户名已存在”),响应拦截器已把这种情况抛为Promise.reject,业务代码catch后提示msg

api.post('/user/register', { username: 'test' })
  .then(data => { /* 成功 */ })
  .catch(err => {
    if (err.message === '用户名已存在') {
      alert('该用户名已被注册,请换一个~');
    } else {
      alert('注册失败:' + err.message);
    }
  });

怎么优化Axios请求的性能和体验?

光会发请求不够,得考虑性能和用户体验,比如避免重复请求、加loading、缓存数据等。

取消重复请求:避免多次请求同一接口

用户快速点击“刷新”时,用AbortController取消之前的请求:

import { AbortController } from 'react-native'; // RN的AbortController
let abortController = null;
const fetchData = () => {
  // 取消未完成的请求
  if (abortController) abortController.abort();
  abortController = new AbortController();
  api.get('/data', { signal: abortController.signal })
    .then(data => { /* 处理数据 */ })
    .catch(err => {
      if (err.name === 'AbortError') {
        console.log('请求被取消');
      } else {
        // 处理其他错误
      }
    });
};

连续点击时,只会保留最后一次请求,减少资源浪费。

请求缓存:避免重复拉取相同数据

对不常变化的接口(如首页轮播图),用MapAsyncStorage缓存:

const cache = new Map();
const fetchBanner = () => {
  const cacheKey = 'banner-data';
  if (cache.has(cacheKey)) {
    return Promise.resolve(cache.get(cacheKey)); // 直接返回缓存
  }
  return api.get('/banner')
    .then(data => {
      cache.set(cacheKey, data); // 存入缓存
      return data;
    });
};

管理loading状态:提升用户体验

发请求时显示loading,结束后隐藏,结合React Hook(如useState)很方便:

import { useState } from 'react';
import { View, ActivityIndicator, Button, FlatList } from 'react-native';
const HomeScreen = () => {
  const [isLoading, setIsLoading] = useState(false);
  const [bannerData, setBannerData] = useState([]);
  const fetchBanner = () => {
    setIsLoading(true);
    api.get('/banner')
      .then(data => {
        setBannerData(data);
        setIsLoading(false);
      })
      .catch(err => {
        setIsLoading(false);
        alert('获取轮播图失败');
      });
  };
  return (
    <View>
      {isLoading ? (
        <ActivityIndicator />
      ) : (
        <FlatList
          data={bannerData}
          renderItem={({ item }) => <BannerItem item={item} />}
        />
      )}
      <Button title="刷新" onPress={fetchBanner} />
    </View>
  );
};

实战场景:登录功能里的Axios调用咋做?

以“用户登录”为例,串起前面知识点:

步骤1:搭建登录界面

TextInput输入账号、密码,Button触发登录:

import { View, TextInput, Button, Alert } from 'react-native';
import { useState } from 'react';
import api from './api'; // 封装好的Axios实例
const LoginScreen = ({ navigation }) => {
  const [username, setUsername] = useState('');
  const [password, setPassword] = useState('');
  const handleLogin = () => {
    // 登录逻辑写这里
  };
  return (
    <View>
      <TextInput
        placeholder="用户名"
        value={username}
        onChangeText={setUsername}
      />
      <TextInput
        placeholder="密码"
        value={password}
        onChangeText={setPassword}
        secureTextEntry
      />
      <Button title="登录" onPress={handleLogin} />
    </View>
  );
};

步骤2:发起登录请求(POST)

handleLogin里发请求,处理成功/失败:

const handleLogin = () => {
  if (!username || !password) {
    Alert.alert('提示', '请填写账号和密码~');
    return;
  }
  api.post('/user/login', { username, password })
    .then(res => {
      // 登录成功,res是响应拦截器处理后的数据(假设含token、userInfo)
      const { token, userInfo } = res;
      // 存储token到本地
      AsyncStorage.setItem('token', token);
      // 跳转到首页
      navigation.replace('Home');
      Alert.alert('成功', '登录成功~');
    })
    .catch(err => {
      // 处理错误
      if (err.response?.data?.msg) {
        Alert.alert('失败', err.response.data.msg);
      } else {
        Alert.alert('失败', '网络或服务器错误,请重试~');
      }
    });
};

步骤3:结合拦截器自动带token

前面封装的api.js请求拦截器,会自动从AsyncStorage取token加到请求头,后续接口(如获取用户信息)无需手动加token,拦截器自动处理~

看完这些,你应该对React Native里用Axios发请求有清晰思路了:从基础安装、请求写法,到拦截器提效、错误处理,再到性能优化和实战场景,每个环节都对应开发里的实际需求,Axios的核心是“简化HTTP请求流程+统一处理逻辑”,结合RN的特性(比如FormData上传文件),能帮你更高效地和后端对接,要是开发中遇到具体问题(比如拦截器配置不生效),可以再针对性排查~现在就把这些技巧用到项目里,让网络请求这块更丝滑吧~

您的支持是我们创作的动力!
温馨提示:本文作者系Terry ,经Web前端之家编辑修改或补充,转载请注明出处和本文链接:
https://www.jiangweishan.com/article/reacttivjsdg2sdf.html

网友评论文明上网理性发言 已有0人参与

发表评论: