React Ts 项目配置 Axios
React项目Ts版,使用Hooks API。本示例主要是配置Axios并使用Eggjs写了两个接口进行测试。
·
React Hooks Ts Axios
React项目Ts版,使用Hooks API。本示例主要是配置Axios并使用Eggjs写了两个接口进行测试。
主要看 ./src/api 和 ./src/model 目录。
├── src
│ ├── api
│ │ ├── api.ts
│ │ └── status.ts
│ ├── model
│ │ └── login.ts
./src/api/api.ts
import axios, {AxiosInstance, AxiosRequestConfig, AxiosResponse} from 'axios';
import qs from 'qs'
import { showMessage } from "./status";
import { message, Spin } from 'antd';
import { ILogin, IUser } from 'model/login';
// 返回res.data的interface
export interface IResponse {
code: number | string;
data: any;
msg: string;
}
let axiosInstance:AxiosInstance = axios.create({
baseURL: process.env.REACT_APP_BASE_URL,
headers: {
Accept: "application/json",
"Content-Type": "application/x-www-form-urlencoded"
},
transformRequest: [
function(data) {
//由于使用的 form-data传数据所以要格式化
delete data.Authorization;
data = qs.stringify(data);
return data;
}
]
});
// axios实例拦截响应
axiosInstance.interceptors.response.use(
(response: AxiosResponse) => {
if (response.headers.authorization) {
localStorage.setItem('app_token', response.headers.authorization);
} else {
if (response.data && response.data.token) {
localStorage.setItem('app_token', response.data.token);
}
}
if (response.status === 200) {
return response;
} else {
showMessage(response.status);
return response;
}
},
// 请求失败
(error: any) => {
const {response} = error;
if (response) {
// 请求已发出,但是不在2xx的范围
showMessage(response.status);
return Promise.reject(response.data);
} else {
message.error('网络连接异常,请稍后再试!');
}
}
);
// axios实例拦截请求
axiosInstance.interceptors.request.use(
(config: AxiosRequestConfig) => {
const token = localStorage.getItem('app_token');
if (token) {
config.headers.Authorization = `Bearer ${token}`
}
return config;
},
(error:any) => {
return Promise.reject(error);
}
)
/**
* @description: 用户登录
* @params {ILogin} params
* @return {Promise}
*/
export const Login = (params: ILogin): Promise<IResponse> => {
return axiosInstance.post('user/login',params).then(res => res.data);
};
/**
* @description: 通过id获取用户
* @params {IUser} params
* @return {Promise}
*/
export const getUserInfo = (params: IUser): Promise<IResponse> => {
return axiosInstance.post('user/getInfo',params).then(res => res.data);
};
- 本文件创建 axios 实例,通过给实例添加请求和响应拦截,做对应处理。
- axios.create 中 transformRequest 配置,先删除参数中的 Authorization, 再通过 qs (npm install @types/qs) 依赖转换了参数的形式(将对象字面量转化成 Form Data 格式)。
- 响应拦截中做了对 token 的处理
- 请求拦截中在请求头部 header 中给 Authorization 添加 token,根据具体业务需求修改。
- 本文件创建一个登录接口 login 和获取用户信息的接口 getUserInfo 用来测试 eggjs 提供的接口。
- 为了统一处理,所有请求均使用 post 方式
./src/api/status.ts
export const showMessage = (status:number|string) : string => {
let message:string = "";
switch (status) {
case 400:
message = "请求错误(400)";
break;
case 401:
message = "未授权,请重新登录(401)";
break;
case 403:
message = "拒绝访问(403)";
break;
case 404:
message = "请求出错(404)";
break;
case 408:
message = "请求超时(408)";
break;
case 500:
message = "服务器错误(500)";
break;
case 501:
message = "服务未实现(501)";
break;
case 502:
message = "网络错误(502)";
break;
case 503:
message = "服务不可用(503)";
break;
case 504:
message = "网络超时(504)";
break;
case 505:
message = "HTTP版本不受支持(505)";
break;
default:
message = `连接出错(${status})!`;
}
return `${message},请检查网络或联系管理员!`;
};
- status.ts 返回相应状态对应的信息文字。
./src/model/login.ts
export interface ILogin {
username: string;
password: string;
}
export const createEmptyLogin = (): ILogin => ({
username: "",
password: ""
});
export interface IUser {
userId: string;
}
- 这里集中定义各种接口相关的 interface。
测试登录接口,只列出主要逻辑:
...
import { ILogin } from "model/login";
import { IResponse, Login } from 'api/api';
import { Button, message } from 'antd';
...
export default () => {
...
// 登录按钮逻辑
const handleLogin = async (login:ILogin) => {
// 调用登录Api,获取结果
let res:IResponse = await Login(login);
// 处理结果
if( res.code === 200 ){
if(res.data.user_id){
localStorage.setItem('user_id', res.data.user_id);
}
// 提示登录成功
message.success(res.msg);
}else{
// 提示登录失败
message.error(res.msg);
}
};
...
return (
<>
<Button
type="ghost"
onClick={() => handleLogin({username:'admin',password:'123456'})}
>登陆</Button>
</>
)
}
用eggjs写个登录接口,返回的json结构是这样。
{
"code":200,
"msg":"登录成功",
"data":{
"user_id": "57c4dda0b42521e3994aa5196ae79485",
"token": "1yJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.2yJ1c2VybmFtZSI6InNvbmljIiwiaWFwIjoxNjE5NDkxMzIzfQ.uIlcV-hO2FZgskyBorMfoUi2tN69MU51XXEbtMN2BZQ"
}
}
- 登录成功后将 user_id 存入本地存储。
- 登录接口请求头部不带 authorization ,登录成功后将 token 存入本地存储, ./src/api/api.ts 中做了这样的处理。
再看获取用户信息的接口。
import React,{ useState, useEffect } from "react";
import { Button } from 'antd';
import { IResponse, getUserInfo } from 'api/api';
import { IUser } from "model/login";
export default () => {
const [user, setUser] = useState<IUser>({ userId: String(localStorage.getItem('user_id')) || "" });
const [userInfo, setUserInfo] = useState<any>(null);
// 获取用户信息
const showUserInfo = async (user:IUser) => {
let res = await getUserInfo(user);
console.log(res);
setUserInfo(res.data);
}
// 组件加载完后执行
useEffect(()=>{
// 调用获取用户信息接口
showUserInfo(user);
},[]);
return(
<>
<Button
style={{'width':'200px'}}
type="primary"
onClick={() => showUserInfo(user)}
>获取用户信息</Button>
<p>{JSON.stringify(userInfo)}</p>
</>
)
}
- useEffect 当作 componentDidMount 生命周期使用,里面的逻辑是页面默认调用获取用户信息接口。
- 点击按钮也可调用一次接口。
获取用户信息返回的json结构
{
"code":200,
"msg":"获取用户信息成功",
"data":{
"user_id": "57c4dda0b42521e3994aa5196ae79485",
"name": "admin",
"real_name": "张一",
"user_role":2,
"headimg": null,
"login_time": 1564994793122,
}
}
最后几点
- 关于 env 的配置,区别于 Vue,VUE_APP_BASE_URL 改成了 REACT_APP_BASE_URL
- 测试接口参考之前一篇文章《vue3.0 ts版项目配置axios》
更多推荐
已为社区贡献3条内容
所有评论(0)