React基础框架搭建8-axios封装与未封装,实现 API 请求管理:react+router+redux+axios+Tailwind+webpack

npm install axios

一、api基础使用(未封装)

1、在 src/api/ 目录下创建一个新的文件 productService.js,用于管理所有的 API 请求。

javascript 复制代码
import axios from 'axios';

// 设置基础 URL
const apiClient = axios.create({
    baseURL: '/', // 使用相对路径来访问 public 目录中的文件
    headers: {
        'Content-Type': 'application/json',
    },
});

// 获取产品列表
export const fetchProducts = async () => {
    const response = await apiClient.get('/product.json'); // 从 public 目录获取 JSON 文件
    return response.data.products; // 返回数据
};

// 添加新产品(模拟)
export const createProduct = async (product) => {
    return product; // 直接返回新产品
};

// 删除产品(模拟)
export const deleteProduct = async (id) => {
    return id; // 返回删除的产品 ID
};

更新 Redux Slice

在 productSlice.js 中,可以添加异步操作来处理 API 请求。使用 Redux Toolkit 的 createAsyncThunk 来创建异步操作。

更改producSlice.js

javascript 复制代码
//src/features/Produc/producSlice.js

import { createSlice, createAsyncThunk } from '@reduxjs/toolkit';
import { fetchProducts, createProduct, deleteProduct } from '../../api/api'; // 引入 API 请求

// 异步获取产品列表
export const fetchProductsAsync = createAsyncThunk('product/fetchProducts', async () => {
    const response = await fetchProducts(); // 调用 API 获取产品
    return response; // 返回产品数据
});

// 异步添加新产品
export const addProductAsync = createAsyncThunk('product/addProduct', async (product) => {
    const response = await createProduct(product);
    return response; // 返回新产品
});

// 异步删除产品
export const removeProductAsync = createAsyncThunk('product/removeProduct', async (id) => {
    await deleteProduct(id);
    return id; // 返回删除的产品 ID
});

const productSlice = createSlice({
    name: 'product',
    initialState: {
        products: [], // 初始为空
        status: 'idle', // 状态管理
    },
    reducers: {},
    extraReducers: (builder) => {
        builder
            .addCase(fetchProductsAsync.fulfilled, (state, action) => {
                state.products = action.payload; // 设置产品列表
            })
            .addCase(addProductAsync.fulfilled, (state, action) => {
                state.products.push(action.payload); // 添加新产品
            })
            .addCase(removeProductAsync.fulfilled, (state, action) => {
                state.products = state.products.filter(product => product.id !== action.payload); // 根据 ID 移除产品
            });
    },
});

// 导出 reducer
export default productSlice.reducer;

更新组件以使用 API

在 ProductList.jsx 和 FeedbackForm.jsx 中,您需要使用这些异步操作来获取和添加产品。

javascript 复制代码
// src/views/Product/ProductList.jsx 

import React, { useEffect } from 'react';
import { useSelector, useDispatch } from 'react-redux';
import { fetchProductsAsync, removeProductAsync } from '../../features/Product/productSlice';


const ProductList = () => {
    const products = useSelector((state) => state.product.products);
    const dispatch = useDispatch();

    useEffect(() => {
        dispatch(fetchProductsAsync()); // 获取产品列表
    }, [dispatch]);

    const handleRemoveProduct = (id) => {
        dispatch(removeProductAsync(id)); // 删除
    };

    return (
        <div className="mt-10">
            <h2 className="font-semibold">产品列表</h2>
            <ul className="list-disc pl-5">
                {products.length > 0 ? (
                    products.map(product => (
                        <li key={product.id} className="mb-1 flex justify-between items-center">
                            {product.name}
                            <button
                                onClick={() => handleRemoveProduct(product.id)}
                                className="ml-4 text-red-500 hover:text-red-700"
                            >
                                删除
                            </button>
                        </li>
                    ))
                ) : (
                    <li>没有产品可显示</li>
                )}
            </ul>
        </div>
    );
};

export default ProductList;

二、封装api

1、在 src/api/ 目录下创建一个新的文件api.js

javascript 复制代码
import axios from 'axios';

// 创建 Axios 实例
const apiClient = axios.create({
    baseURL: 'http://localhost:3000', // 使用 json-server 的基础路径
    timeout: 10000, // 超时时间
    headers: {
        'Content-Type': 'application/json',
    },
});

// 请求拦截器
apiClient.interceptors.request.use(
    (config) => {
        // 在请求发送之前做些什么,例如添加 token
        const token = localStorage.getItem('token'); // 假设 token 存储在 localStorage

        // 检查请求的 URL 是否需要 token
        const noAuthRequired = ['/login', '/register']; // 不需要 token 的请求列表

        if (token && !noAuthRequired.some(url => config.url.startsWith(url))) {
            config.headers['Authorization'] = `Bearer ${token}`; // 添加 token
        }
        return config;
    },
    (error) => {
        // 处理请求错误
        return Promise.reject(error);
    }
);

// 响应拦截器
apiClient.interceptors.response.use(
    (response) => {
        // 统一处理返回数据
        return response.data; // 直接返回数据
    },
    (error) => {
        // 处理错误
        const { response } = error;
        if (response) {
            // 根据 HTTP 状态码处理不同的错误
            switch (response.status) {
                case 401:
                    alert('未授权,请登录!');
                    break;
                case 404:
                    alert('请求的资源未找到!');
                    break;
                case 500:
                    alert('服务器错误,请稍后再试!');
                    break;
                default:
                    alert('发生错误,请重试!');
            }
        } else {
            alert('网络错误,请检查您的网络连接!');
        }
        return Promise.reject(error);
    }
);

// 封装请求方法
const api = {
    get: (url, params) => apiClient.get(url, { params }),
    post: (url, data) => apiClient.post(url, data),
    put: (url, data) => apiClient.put(url, data),
    delete: (url) => apiClient.delete(url),
};

export default api;

使用:

dart 复制代码
// 异步获取产品列表
export const fetchProductsAsync = createAsyncThunk('product/fetchProducts', async () => {
    const response = await api.get('/products'); // 使用封装的 GET 方法
    return response; // 返回产品数据
});

// 异步添加新产品
export const addProductAsync = createAsyncThunk('product/addProduct', async (product) => {
    const response = await api.post('/products', product); // 使用封装的 POST 方法
    return response; // 返回新产品
});

// 异步删除产品
export const removeProductAsync = createAsyncThunk('product/removeProduct', async (id) => {
    await api.delete(`/products/${id}`); // 使用封装的 DELETE 方法
    return id; // 返回删除的产品 ID
});
相关推荐
攀登的牵牛花18 分钟前
前端向架构突围系列 - 架构方法(二):UML前端建模的一般方法和工具
前端·前端框架·uml
chao_66666619 分钟前
React Native + Expo 开发指南:编译、调试、构建全解析
javascript·react native·react.js
码丁_1171 小时前
某it培训机构前端三阶段react及新增面试题
前端·react.js·前端框架
_pengliang1 小时前
react native ios 2个modal第二个不显示
javascript·react native·react.js
我算哪枝小绿植2 小时前
react实现日历拖拽效果
前端·react.js·前端框架
OEC小胖胖2 小时前
04|从 Lane 位图到 `getNextLanes`:React 更新优先级与纠缠(Entangle)模型
前端·react.js·前端框架
愤怒的可乐2 小时前
从零构建大模型智能体:ReAct 智能体实战
前端·react.js·前端框架
BlackWolfSky2 小时前
React中文网课程笔记4—常用工具配置
前端·笔记·react.js
巾帼前端2 小时前
前端框架 React 的虚拟 DOM是如何在这一层层抽象中定位自己位置的?
前端·react.js·前端框架
wayne2142 小时前
React Native 0.80 学习参考:一个完整可运行的实战项目
学习·react native·react.js