最强大、最接地气的请求Hooks: useRequest

11,058 阅读3分钟

本文已参与「新人创作礼」活动,一起开启掘金创作之路。

前言

你有没有为各种请求数据感到烦恼,请求的时候需要防抖节流轮询SWR等附加功能的实现所困扰,当你知道这些功能只需要一个简简单单的钩子就能实现,那么你还不盘他

src=http___img.adoutu.com_article_1593770018660.jpg&refer=http___img.adoutu.jpeg

用官方的话说: useRequest 是一个强大的异步数据管理的 Hooks,React 项目中的网络请求场景使用 useRequest 就够了。

这个Hook可以说是整个 ahooks 最重要的钩子了,同时useRequest 也是 umi 主推的钩子,当然我们使用的Ant Design Pro V5 也是建议使用此钩子。

感觉官方的意思就是 没有useRequest 处理不了的情况, 那么它的组要功能有那些呢?

  • 自动请求/手动请求
  • 轮询
  • 防抖
  • 节流
  • 屏幕聚焦重新请求
  • 错误重试
  • loading delay
  • SWR(stale-while-revalidate)
  • 缓存

我们从官网上看到的这些功能的确满足了开发的需求(至少我做过的项目都满足了(● ̄(エ) ̄●)),接下来,我要介绍一下个人觉得非常好的功能,

项目展示 Domesy/useRequest

基本使用+手动请求

先简单介绍一下 useRequest 的参数, 第一个参数是一个异步函数,第二个参数为各项配置。同时自动管理该异步函数的loadingdataerror

手动请求: 可设置初始值,配置请求接口的参数,并且能根据请求成功做对应的东西,设置初始请求值,loading状态等

image.png

代码展示

import React, { useState } from 'react';
  import { useRequest } from 'umi';
  import { Button } from 'antd';

  const Mock: React.FC<any> = () => {
    const [count,  setCount ] = useState<number>(0)

    const { data, loading , run } = useRequest({
      url: 'hook/useRequest/test',
      method: 'POST',
      data: {
        param: '11'
      }
    },{
      manual: true,
      initialData: '未请求',
      onSuccess: (result:any, params) => {
        if (result) {
          setCount(count + params[0]);
        }
      }
    })

    return (
      <div>
        <div style={{marginBottom: 20}}>count: {count}</div>
        <div style={{marginBottom: 20}}>count: {data.message ? data.message : data}</div>
        <Button loading={loading} type='primary' onClick={() => run(count + 1)}>手动请求</Button>
      </div>
    );
  };

  export default Mock;

轮询

轮询的效果:隔一段时间就会请求,这个效果还是非常常见的

可通过 run 和 cancel 轻松实现轮讯效果,pollingInterval 如果存在,则开始轮询效果

我们做个简单的案例, 让他每隔1s,就自动请求

image.png

代码示例

import React from 'react';
  import { useRequest } from 'umi';
  import { Button, Spin } from 'antd';

  const MockPooling: React.FC<any> = () => {
    const { data, loading, run, cancel } = useRequest('hook/useRequest/pooling', {
      manual: true,
      pollingInterval: 1000,
      pollingWhenHidden: false
    })

    return <>
      <Spin spinning={loading}>
        <p>姓名为:{data?.name || '请开始'}</p>
      </Spin>
      <Button style={{marginTop: 20}} type='primary' onClick={run} >开始</Button>
      <Button style={{marginLeft: 24}} onClick={cancel} >停止</Button>
    </>
  };

  export default MockPooling;

缓存 & SWR

SWR :通过设置 cacheKey, 可以将 useRequest 请求的数据缓存, 下次组件初始化,如果有缓存数据,会优先返回缓存数据,同时也在发送新的请求,然后进行替换,这就是 SWR 能力

image.png

代码示例

  import React from 'react';
  import { useRequest } from 'umi';
  import { Button, Spin } from 'antd';
  import { Mock } from 'mockjs';

  const MockCache: React.FC<any> = () => {
    const [show, setShow] = useState<boolean>(false)

    const { data, run, loading } = useRequest('hook/useRequest/cache', {
      manual: true,
      cacheKey: 'article'
    })

    return <>
      <Button type='primary' onClick={() => { setShow(!show); run()}} >{show ? '隐藏' : '展开'}</Button>
      {
        show && <Spin spinning={!data && loading}>
          <p>上次更新的时间:{data?.time}</p>
          <p>更新内容</p>
          <p>{data?.data}</p>
        </Spin>
      }
    </>
  };

  export default MockCache;

依赖刷新

依赖刷新: 通过某个状态自动请求数据,其 refreshDeps 的用法与 useEffect 使用的方法相同

这个功能简直不要太好用,我们有太多太多的时候需要使用到,大大减少其开发时间,简直爽到天(● ̄(エ) ̄●)

image.png

代码示例

import React, { useState } from 'react';
  import { useRequest } from 'umi';
  import { Select } from 'antd';

  const Mock: React.FC<any> = () => {
    const [id,  setId] = useState<string>('1')

    const { data, loading } = useRequest({
      url: 'hook/useRequest/test',
      method: 'POST',
      data: {
        param: '11'
      }
    }, {
      refreshDeps: [id],
    });

    return (
      <>
       <div>
        <Select value={id} style={{ width: 120 }} onChange={(e) => setId(e)}>
            <Select.Option value="1">依赖1</Select.Option>
            <Select.Option value="2">依赖2</Select.Option>
              <Select.Option value="3">依赖3</Select.Option>
          </Select>
       </div>
        <div>当前依赖项:{loading ? 'loading' : data.message: 依赖id改变}</div>
      </>
    );
  };

  export default Mock;

结束

以上四个案例是我觉得最常见,其效果非常好的案例,可以说这个钩子是非常非常 nice 的,希望能尽一点绵薄之力帮助各位(● ̄(エ) ̄●)