封装fetch(例如携带token)
继续记录自己学习React的心得
封装fetch
为了让每个请求都携带token,同时减少工作量和duplicate code,封装一下fetch还是很有必要的。本项目中将fetch封装为http模块。
- 需要用到qs库
// package.json { ..., "dependencies": { "qs": "^6.10.3", ... }, }
- http模块支持配置fetch config,因此需要创建Config接口以及相关操作
// http.ts
interface Config extends RequestInit { token?: string; data?: object; } export const http = async ( endpoint: string, { data, token, headers, ...customConfig }: Config = {} ) => { const config = { method: "GET", headers: {
// 如果customConfig中传入了token,则会在这里将token添加到headers Authorization: token ? `Bearer ${token}` : "", "Content-Type": data ? "application/json" : "", }, ...customConfig, }; ... }模块默认GET请求,headers中的Authorization是指定的写法。
- 主要逻辑
(1)先对GET/POST请求进行不同处理
if (config.method.toUpperCase() === "GET") { // GET请求直接在endpoint中添加参数 endpoint += `?${qs.stringify(data)}`; } else { // POST则在body中JSON序列化数据 config.body = JSON.stringify(data || {}); }
(2)发送fetch请求
export const http = async ( endpoint: string, { data, token, headers, ...customConfig }: Config = {} ) => { ...... return window.fetch(`${apiUrl}/${endpoint}`, config).then(async (res) => {
// 401 Unauthorized,登出 if (res.status === 401) { await auth.logout; window.location.reload(); return Promise.reject({ message: "请重新登录" }); }
// res.json()需要await const data = await res.json(); if (res.ok) { return data; } else { return Promise.reject(data); } }); }; - 传出useHttp hook
export const useHttp = () => {
// useAuth是用户认证模块的hook const { user } = useAuth();
return ([endpoint, config]: [string, Config]) => http(endpoint, { ...config, token: user?.token }); };
// 或者可以用下面的写法,这里的[string, Config]和http()传入的参数类型一致,因此可以使用Parameters<typeof http>,这样保持和http()的代码上下一致,不写重复代码
// return (...[endpoint, config]: Parameters<typeof http>) => http(endpoint, { ...config, token: user?.token }); };
} - 用法
例如获取用户列表接口,就使用到了useHttp:
export const useUsers = (param?: Partial<User>) => { const client = useHttp(); const { run, ...result } = useAsync<User[]>(); useEffect(() => { run(client("users", { data: cleanObject(param || {}) })); }, [param]); return result; };

浙公网安备 33010602011771号