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
});