1. 首页
  2. React

Vite6+React18+Ts项目-05.集成阿里巴巴ahooks及使用useRequest

Ahooks 是阿里巴巴开源的一个高质量的 React Hooks 库,提供了大量实用的自定义 Hooks,可以帮助开发者提高开发效率,减少重复代码。

1.安装

npm install ahooks

2.数据类型及Api接口

调用 useRequest 之前,我们需要先定义数据类型和实现一个简单的api接口

定义数据类型 src\types\user.ts

export interface UserResp {
  id: number;
  name: string;
}
export interface UserSaveReq {
  id: number;
  name: string;
}

实现请求接口 src\apis\user.ts

import { http } from '@/server/http';
import { UserResp, UserSaveReq } from '@/types/user';

export class UserApi {
  // 获取详情
  static get(id: number) {
    return http.get<{ id: number }, UserResp>(
      'http://demo.com/api.php?sleep=1',
      {
        id: id,
      }
    );
  }
  // 保存用户信息
  static save(data: UserSaveReq) {
    return http.post<UserSaveReq, UserResp>('http://demo.com/api.php', data);
  }
}

3.使用 useRequest 管理异步请求

// src/components/UserList.tsx
import React from 'react';
import { useRequest } from 'ahooks';
import { getUserList } from '../services/userService';

interface User {
  id: number;
  name: string;
  email: string;
}

const UserList: React.FC = () => {
  const { data, loading, error } = useRequest(() => UserApi.get(1));

  if (loading) return <div>Loading...</div>;
  if (error) return <div>Error: {error.message}</div>;

  return (
    <div>
      <p>{data && <p> {JSON.stringify(data)}</p>}</p>
    </div>
  );
};

export default UserList;

4.使用 Promise.all 组合多个请求

下面的内容实现了自动管理loading,error状态

import useRequest from '@/components/use-request';

import { UserApi } from '@/apis/user';
import { Button } from 'antd';
import { useState } from 'react';

export default function Eg06() {
  const [count, setCount] = useState<number>(1);

  // 使用 Promise.all 组合多个请求
  const { loading, data, run } = useRequest(async () => {
    const [one, two] = await Promise.all([UserApi.get(count), UserApi.get(1)]);
    return { one, two };
  });

  return (
    <div
      style={{
        padding: '100px',
        border: '1px solid red',
      }}
    >
      <p>计数:{count}</p>
      <Button onClick={() => setCount(count + 1)}>增加1</Button>
      <Button onClick={run}>查询</Button>
      <p>{loading && <p>Loading...</p>}</p>
      <p>all: {!loading && JSON.stringify(data?.one.data)}</p>
    </div>
  );
}

这里实现了代码自动提示

image.png

5.使用串行请求(一个请求的结果作为另一个请求的参数)

方法一:使用依赖请求

import useRequest from '@/components/use-request';

import { UserApi } from '@/apis/user';

export default function Eg06() {
  
  // 使用依赖请求(一个请求的结果作为另一个请求的参数)
  const { data: first } = useRequest(() => UserApi.get(1));
  const { data: second } = useRequest(
    () => UserApi.save(first?.data as userSaveReq),
    {
      // 只有当 first 存在时才执行
      ready: !!first,
    }
  );

  return (
    <div
      style={{
        padding: '100px',
        border: '1px solid red',
      }}
    >
      <p>依赖请求</p>
      <p>first:</p>
      <p>{first && <p> {JSON.stringify(first)}</p>}</p>
      <p>second:</p>
      <p>{second && <p> {JSON.stringify(second)}</p>}</p>
    </div>
  );
}

方法二:使用 runAsync + then 链式调用

import { useRequest } from 'ahooks';

function Demo() {
  // 第一个请求
  const { runAsync: runFirstRequest } = useRequest(
    (params) => fetchFirstData(params),
    { manual: true } // 手动触发
  );

  // 第二个请求(依赖第一个请求的结果)
  const { run: runSecondRequest } = useRequest(
    (secondParams) => fetchSecondData(secondParams),
    { manual: true }
  );

  const handleClick = async () => {
    try {
      // 1. 先执行第一个请求
      const firstResult = await runFirstRequest({ id: 1 });
      
      // 2. 用第一个请求的结果发起第二个请求
      runSecondRequest({ data: firstResult.data });
    } catch (error) {
      console.error(error);
    }
  };

  return <button onClick={handleClick}>Start Requests</button>;
}

方法三:使用 useRequest 的 onSuccess 回调

import { useRequest } from 'ahooks';

function Demo() {
  // 第一个请求
  const { run: runFirstRequest } = useRequest(
    (params) => fetchFirstData(params),
    {
      manual: true,
      onSuccess: (firstResult) => {
        // 当第一个请求成功时,自动发起第二个请求
        runSecondRequest({ data: firstResult.data });
      }
    }
  );

  // 第二个请求
  const { run: runSecondRequest } = useRequest(
    (secondParams) => fetchSecondData(secondParams),
    { manual: true }
  );

  return <button onClick={() => runFirstRequest({ id: 1 })}>Start Requests</button>;
}

方法四:直接嵌套请求(适用于强依赖关系)

import { useRequest } from 'ahooks';

function Demo() {
  const { run: runNestedRequest } = useRequest(
    async (params) => {
      // 1. 先执行第一个请求
      const firstResult = await fetchFirstData(params);
      // 2. 用第一个结果发起第二个请求
      const secondResult = await fetchSecondData({ data: firstResult.data });
      // 3. 返回两个请求的结果
      return { firstResult, secondResult }
    },
    { manual: true }
  );

  return <button onClick={() => runNestedRequest({ id: 1 })}>Start Requests</button>;
}

TOP