教程 axios tutorial

结合 Pinia / Redux 管理请求状态

在前端项目中,Axios 通常与状态管理库(如 Pinia、Redux)配合使用,以实现全局统一的请求状态(loading、error、data)管理。
这可以让组件逻辑更清晰,避免重复的请求控制代码。

一、在 Vue3 + Pinia 中使用 Axios

Pinia 是 Vue3 官方推荐的状态管理库,搭配 Axios 可以轻松管理异步数据请求。

1. 安装依赖

bash
npm install pinia axios

`

在入口文件中注册 Pinia:

js
// main.js
import { createApp } from "vue";
import { createPinia } from "pinia";
import App from "./App.vue";

const app = createApp(App);
app.use(createPinia());
app.mount("#app");

2. 创建 Axios 实例

js
// src/utils/request.js
import axios from "axios";

const request = axios.create({
  baseURL: "/api",
  timeout: 8000,
});

request.interceptors.response.use(
  (res) => res.data,
  (err) => Promise.reject(err)
);

export default request;

3. 定义 Pinia Store

js
// src/stores/user.js
import { defineStore } from "pinia";
import request from "../utils/request";

export const useUserStore = defineStore("user", {
  state: () => ({
    list: [],
    loading: false,
    error: null,
  }),
  actions: {
    async fetchUsers() {
      this.loading = true;
      this.error = null;
      try {
        const res = await request.get("/users");
        this.list = res;
      } catch (err) {
        this.error = err.message || "请求失败";
      } finally {
        this.loading = false;
      }
    },
  },
});

4. 在组件中使用

vue
<template>
  <div>
    <button @click="fetchUsers">加载用户</button>
    <p v-if="loading">加载中...</p>
    <p v-if="error" class="error">{{ error }}</p>
    <ul>
      <li v-for="u in list" :key="u.id">{{ u.name }}</li>
    </ul>
  </div>
</template>

<script setup>
import { useUserStore } from "../stores/user";
const { list, loading, error, fetchUsers } = useUserStore();
</script>

✅ 优势:

  • 统一管理加载与错误状态
  • 方便复用与缓存
  • 更好地解耦组件与请求逻辑

二、在 React + Redux Toolkit 中使用 Axios

Redux Toolkit 提供了 createAsyncThunk 来封装异步请求逻辑,非常适合与 Axios 结合使用。

1. 安装依赖

bash
npm install @reduxjs/toolkit react-redux axios

2. 创建 Axios 实例

js
// src/api/request.js
import axios from "axios";

const request = axios.create({
  baseURL: "/api",
  timeout: 8000,
});

request.interceptors.response.use(
  (res) => res.data,
  (err) => Promise.reject(err)
);

export default request;

3. 定义 Slice 与异步请求

js
// src/store/userSlice.js
import { createSlice, createAsyncThunk } from "@reduxjs/toolkit";
import request from "../api/request";

export const fetchUsers = createAsyncThunk("users/fetch", async () => {
  return await request.get("/users");
});

const userSlice = createSlice({
  name: "user",
  initialState: { list: [], loading: false, error: null },
  reducers: {},
  extraReducers: (builder) => {
    builder
      .addCase(fetchUsers.pending, (state) => {
        state.loading = true;
        state.error = null;
      })
      .addCase(fetchUsers.fulfilled, (state, action) => {
        state.loading = false;
        state.list = action.payload;
      })
      .addCase(fetchUsers.rejected, (state, action) => {
        state.loading = false;
        state.error = action.error.message;
      });
  },
});

export default userSlice.reducer;

4. 配置 Store

js
// src/store/index.js
import { configureStore } from "@reduxjs/toolkit";
import userReducer from "./userSlice";

const store = configureStore({
  reducer: {
    user: userReducer,
  },
});

export default store;

在入口文件中注入:

js
// main.jsx
import { Provider } from "react-redux";
import store from "./store";
import App from "./App";

ReactDOM.createRoot(document.getElementById("root")).render(
  <Provider store={store}>
    <App />
  </Provider>
);

5. 在组件中使用

jsx
import React, { useEffect } from "react";
import { useDispatch, useSelector } from "react-redux";
import { fetchUsers } from "../store/userSlice";

function UserList() {
  const dispatch = useDispatch();
  const { list, loading, error } = useSelector((state) => state.user);

  useEffect(() => {
    dispatch(fetchUsers());
  }, [dispatch]);

  if (loading) return <p>加载中...</p>;
  if (error) return <p>错误:{error}</p>;

  return (
    <ul>
      {list.map((u) => (
        <li key={u.id}>{u.name}</li>
      ))}
    </ul>
  );
}

export default UserList;

三、Pinia vs Redux 对比

特性 Pinia(Vue) Redux Toolkit(React)
语法风格 简洁、声明式 结构化、约束性强
异步请求支持 直接写在 actions 中 createAsyncThunk 内置支持
状态管理方式 响应式(Reactive) 不可变(Immutable)
学习曲线 低 中等
类型支持 优秀(TS 友好) 优秀(TS 原生)

四、总结

  • Pinia 适合 Vue3,逻辑直观,轻量易上手。
  • Redux Toolkit 简化了 Redux 使用,推荐用于中大型 React 项目。
  • 两者都可以与 Axios 无缝结合,实现统一请求与状态管理。
  • 对复杂项目,可结合缓存、重试与全局错误提示模块进一步优化。