@qiweipeng/use-axios
TypeScript icon, indicating that this package has built-in type declarations

1.1.4 • Public • Published

useAxios

npm npm npm

基于 AxiosReact Hooks 封装,同时集成 Zod 实现对运行时对象的数据校验。

功能点

  • [x] 完全基于 Axios,使用 Axios 实例创建,各个请求互不影响
  • [x] 完全基于 TypeScript,提供完善的类型定义
  • [x] Zod 支持,保证运行时数据类型安全
  • [x] 网络请求可取消
    • [x] 组件释放自动取消
    • [x] 竞态取消
  • [x] 手动请求(默认)或自动请求
  • [x] loading delay
  • [x] mock
  • [ ] 防抖
  • [ ] 轮询
  • [ ] 错误重试
  • [ ] 依赖刷新

快速开始

安装

yarn add @qiweipeng/use-axios
# 或者
npm install --save @qiweipeng/use-axios

使用

请求详情页示例

import {useAxios} from '@qiweipeng/use-axios';

export function Foo() {
  const {response, error, loading, fetch} = useAxios(
    {
      url: 'https://...',
      method: 'post', // post 请求默认 json 类型,如果希望表单类型则在 headers 中添加 `'Content-Type': 'application/x-www-form-urlencoded'`
      data: {
        id: 0,
      }, // 参数,如果是 get 请求则在 params 中配置
      headers: {
        ''
      },
    },
    {automatic: true}, // 页面加载后自动请求一次
  );

  // 页面加载中,展示加载指示器
  if (loading) {
    return <Text>加载中……</Text>;
  }

  // 页面加载失败,展示错误提示和重试按钮
  if (!response) {
    return (
      <View>
        <Text>页面加载失败</Text>
        <Button
          title="重试"
          onPress={() => {
            fetch();
          }}
        />
      </View>
    );
  }

  // 页面加载成功,展示页面内容
  return <Text>{JSON.stringify(response.data)}</Text>;
}

点击按钮跳转页面请求示例

import {useAxios} from '@qiweipeng/use-axios';

export function Bar() {
  const {loading, fetchAsync} = useAxios({
    url: 'https://...',
    method: 'post',
    data: {
      username: '',
      password: '',
    }, // 参数可以在初始位置填入,也可以在 fetchAsync 调用时传入,如果调用时再传入,这里仅仅描述类型即可
  });

  function handleLoginButtonClick() {
    fetchAsync({
      data: {
        username: 'roger',
        password: '123456',
      }, // 这里会进行类型检查,一定是满足接口定义时的条件,否则报错
    })
      .then(() => {
        // 登录成功,保存 token
      })
      .catch(() => {
        // 登录失败,吐司提示
      });
  }

  return (
    <View>
      <Text>内容</Text>
      <Button title="登录" onPress={handleLoginButtonClick} />
      {/* 页面加载中,展示加载指示器 */}
      {loading && <Spinner />}
    </View>
  );
}

状态流转图

默认情况下网络请求的状态流转过程如下:

flowchart LR

classDef node text-align:left,fill:#fff,stroke:#999,color:#000;

A[response: undefined<br>error: undefined<br>loading: false] -->|"fetch()/fetchAsync()"| B[response: 维持上个状态<br>error: 维持上个状态<br>loading: true]
B -->|成功| C["response: R<br>error: undefined<br>loading: false"]
B -->|失败| D["response: 维持上个状态<br>error: AxiosError<unknown, D> | Error | Cancel<br>loading: false"]
C --> |"fetch()/fetchAsync()"|B
D --> |"fetch()/fetchAsync()"|B

会影响状态流转的 options

  1. loadingDelayloadingDelay 大于 0 时会影响 loading 状态延迟更新。

API

useAxios()

参数

config

config 参数为 Axios 中的 AxiosRequestConfig 类型,具体参见 Request Config

常见的字段如下:

字段 描述
url url
method 请求方法
baseURL base url
headers 请求头
params get请求参数
data 请求体参数
timeout 超时时间

关于 config 的覆盖规则⚠️

  1. fetchAsync 方法调用时传入的 config增量覆盖接口定义时传入的 config,即在保留所有原有字段配置的情况下有该字段则修改,没有该字段则添加
  2. config 中的 paramsdata,在方法调用时同样会增量覆盖。
options(可选)

该字段用于配制接口的功能和行为,完整的描述如下:

option 描述 类型 默认值
automatic 是否是自动请求(如果是自动请求则会在组件加载后进行一次请求) boolean false
loadingDelay loading 状态是否延迟更改,单位为毫秒(请求开始后在 loadingDelay 范围内 loading 状态保持为 false 不变) number 0

返回值

response

类型:R = AxiosResponse<T, D> | undefied

responseundefied 的情况参见状态流转图,其不为 undefied 时是一个 Axios 中的 AxiosResponse 类型,具体参见 Response Schema

error

类型:AxiosError<unknown, D> | Error | Cancel | undefied

errorundefied 的情况参见状态流转图,其不为 undefied 时分三种情况:

  1. Cancel:网络请求取消,其中 Cancel 类型是 Axios 中内置的类型。
  2. AxiosError:网络请求出错,具体参见 Handling Errors
  3. Error:接口配置有误,发生在网络请求开始之前(通常接口参数等填写正确,网络请求能发起,就不会有该错误),具体参见 Handling Errors
loading

类型:boolean

loading 的状态变化参见状态流转图。需要注意的是,如果 options 中设置了 loadingDelay 的值,则其状态变化会发生调整。

fetchAsync

类型:(config?: AxiosRequestConfig<D>) => Promise<R>

发起请求方法,具体用法可参见 点击按钮跳转页面请求示例

💡提示:

接口参数变化不会触发接口调用,唯一会触发接口调用的方式是调用 fetchAsyncfetch 方法。 fetchAsyncfetch 在接口所在组件整个生命周期中不会发生变化,可以放心加入 useEffect 依赖数组中。

fetch

类型:(config?: AxiosRequestConfig<D>) => void

fetch 方法是 fetchAsync 的非异步版本,其内部就是:

fetchDataAsync(c).catch(() => {
  return;
});

当使用 fetch 方法时,请求结果就要依赖 responseerror 两个返回值。

⚠️需要注意的是,网络请求结束到 responseerror 状态的更新是需要经历一次 React 组件的状态更新周期的,也就是说,responseerror 的状态更新会比 fetchAsync 方法回调晚一些。

cancel

类型:() => void

手动取消正在进行的网络请求。

💡提示:

  1. 接口所在组件释放时,正在进行的请求会立即取消。
  2. 同一个接口下一次请求开始时(如多次调用 fetch 方法),上一次未完成的请求会立即取消。
  3. 网络请求取消会被错误捕捉到,因此在进行 fetchAsync 方法的错误处理时,需要考虑 Cancel 类型的处理。
requestInterceptors

类型:AxiosInterceptorManager<AxiosRequestConfig<D>>

请求拦截器,具体参见 Interceptors。其在项目的用法示例如下:

import {useAxios} from '@qiweipeng/use-axios';

export function Baz() {
  const {response, error, loading, fetch, requestInterceptors} = useAxios({
    url: 'https://...',
    method: 'get',
  });

  useEffect(() => {
    const requestInterceptor = requestInterceptors.use(
      c => {
        // 做一些事情
        return c;
      },
      e => {
        // 做一些事情
        return Promise.reject(e);
      },
    );
    return () => {
      requestInterceptors.eject(requestInterceptor);
    };
  }, [requestInterceptors]);

  return <Text>内容</Text>;
}
responseInterceptors

类型:AxiosInterceptorManager<AxiosResponse<T, D>>

响应拦截器,具体参见 Interceptors。其在项目的用法示例如下:

import {useAxios} from '@qiweipeng/use-axios';

export function Qux() {
  const {response, error, loading, fetch, responseInterceptors} = useAxios({
    url: 'https://...',
    method: 'get',
  });

  useEffect(() => {
    const responseInterceptor = responseInterceptors.use(
      r => {
        // 做一些事情
        return r;
      },
      e => {
        // 做一些事情
        return Promise.reject(e);
      },
    );
    return () => {
      responseInterceptors.eject(responseInterceptor);
    };
  }, [responseInterceptors]);

  return <Text>内容</Text>;
}

useValidatedAxios()

useValidatedAxios() 是在 useAxios() 的基础上增加 Zod 库的支持,参数增加 validationSchemaoptions 参数中增加 mock 字段,返回值中 error 的类型增加 ValidationError 类型,除此之外完全相同。使用 useValidatedAxios() 时如果不传 validationSchema 参数则和 useAxios 用法完全一致。

validationSchema(可选)参数

这是一个 Zod 中的 ZodTypeAny 类型,具体参见 Zod

使用中,该参数用于描述 response 中的数据格式,具体可以:

  1. 校验每个字段的类型、是否为空等。
  2. 设置约束字段的具体条件,如 string 类型的长度或是否为 URLnumber 类型是否在某个范围之内等。
  3. 对数据进行转换,如将 gender 字段返回的 01 修改为一个枚举。

应用示例如下:

import {useAxios} from '@qiweipeng/use-axios';
import {z} from 'zod';

export function Fred() {
  const {fetchAsync} = useValidatedAxios(
    {
      url: 'https://...',
      method: 'get',
    },
    undefined,
    z.object({
      name: z.string(),
      phoneNumber: z.number().nullish(),
    }),
  );

  return (
    <Button
      title="获取个人信息"
      onPress={() => {
        fetchAsync()
          .then(response => {
            // ⭐️如果请求成功,那么 response 是类型安全的
            response.data.name; // string
            response.data.phoneNumber; // number | null | undefined
          })
          .catch(() => {
            // 请求失败,包含数据校验失败的情况
          });
      }}
    />
  );
}

options新增字段(可选)

option 描述 类型 默认值
mock 是否使用 mock 数据(如果是则请求一定成功且按照 validationSchema 的描述提供 mock 数据),只在 validationSchema 不为空时才有效;需要注意的是,mock 开启后,请求响应中除了 statusdata 外的字段均有可能为空⚠️ boolean false

参见 zod-mock

ValidationError

ValidationErroruseValidatedAxios() 相比于 useAxios() 新增的一种错误类型,表示数据校验失败的错误。它继承自 ZodZodError,在其基础上增加了 response 属性,可以在错误处理时完整获取到接口返回到 response。其具体实现如下:

class ValidationError<T, D> extends z.ZodError {
  response: AxiosResponse<T, D>;
  constructor(issues: z.ZodIssue[], response: AxiosResponse<T, D>) {
    super(issues);
    this.name = 'ValidationError';
    this.response = response;
  }
}

关于 ZodError 具体参见 Error handling

协议

MIT

Readme

Keywords

Package Sidebar

Install

npm i @qiweipeng/use-axios

Weekly Downloads

0

Version

1.1.4

License

MIT

Unpacked Size

23.6 kB

Total Files

13

Last publish

Collaborators

  • qiweipeng