Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

【V3】useRequest #1173

Closed
brickspert opened this issue Sep 24, 2021 · 22 comments
Closed

【V3】useRequest #1173

brickspert opened this issue Sep 24, 2021 · 22 comments
Assignees
Labels

Comments

@brickspert
Copy link
Collaborator

基础能力

const { 
  data, 
  error, 
  loading
} = useRequest(
  getUsername
);
  • 接收一个 Promise,初始化时默认执行
  • API 释义
    • result.data 🚩 Promise resolve 的值,如果本次是 error,则不清空上一次的 data
    • result.error Promise reject 的值
    • result.loading Promise 是否正在执行
  • 相关 issue:#912#666

手动触发

const {
  run,
  runAsync
} = useRequest(
  (userId, userName) => changeUsername(userId),
  {
    manual: true,
    onError: (result, params)=>{},
    onSuccess: (error, params)=>{}
  }
);

// 用法 A
run(1, 'tom');

// 用法 B
runAsync(1, 'tom').then(()=>{}).catch(()=>{});
  • 如果设置了 options.manual ,则不会自动执行 Promise,需要用 run/runAsync 触发执行
  • API 释义
    • options.manual 手动触发,如果设置为 true,则初始化时不会自动执行
    • options.onSuccess Promise resolve 触发,参数为 resultparamsparams 在上述示例中为 [userId, userName]
    • options.onError Promise reject 触发,参数为 errorparams
    • result.run 🚩 手动触发 Promise 执行,用该方法触发的请求,会自动捕获异常,可以通过 onError 来处理异常情况。
    • result.runAsync 🚩 手动触发 Promise 执行,该方法会返回一个 Promise,需要用户自己处理异常。但 onSuccess/onError 仍然可用。
  • 相关 issue:#812#757#725

轮询

  const { data, loading, run, cancel } = useRequest(getUsername, {
    pollingInterval: 1000,
    pollingWhenHidden: false,
  });
  • 通过设置 options.pollingInterval,进入轮询模式,定时触发函数执行。
  • API 释义
    • options.pollingInterval 🚩 设置轮询间隔,设置后开启轮询模式。该数值支持动态变化,变化后重新开始计时。
    • options. pollingWhenHidden 在屏幕不可见时,暂时暂停定时任务。
  • 其它
    • 通过 run/cancel 来开启/暂停轮询
    • options.manual=true 时,需要第一次执行 run 后,才开始轮询。
  • 相关 issue:#970#711

并行请求

  const { run, fetches } = useRequest(deleteUser, {
    manual: true,
    fetchKey: (id) => id,
    onSuccess: (result, params) => {
      if (result.success) {
        message.success(`Disabled user ${params[0]}`);
      }
    },
  });

	run(1);
  run(2);
  run(3);
  • 通过设置 options.fetchKey,进入并行模式,支持多个请求并行执行,每个请求有自己的状态。
  • API 释义
    • options.fetchKey 参数同 services,用来为每一个请求设置一个 key。
    • result.fetches 所有请求集合,通过 fetches[key] 即可拿到相关请求的数据。

防抖

  const { data, loading, run } = useRequest(getEmail, {
    debounceWait: 500,
    debounceLeading: true,
    debounceTrailing: false,
    manual: true,
  });
  • 通过设置 options.debounceWait ,进入防抖模式。
  • API 释义
    • options.debounceWait 🚩 设置防抖间隔时间
    • options.debounceLeading 🚩 在 leading edge 执行
    • options.debounceTrailing 🚩 在 trailing edge 执行
  • 其它
    • 通过 cancel 可取消正在等待和正在执行的请求
    • runAsync 的 Promise,在真正执行的那一次,需要触发 then
  • 相关 issue:#972#795#788#565

节流

同防抖,不单独写了。

屏幕聚焦重新请求

  const { data, loading } = useRequest(getUsername, {
    refreshOnWindowFocus: true,
    focusTimespan: 5000,
  });
  • 设置了 options.refreshOnWindowFocus,则在浏览器窗口 refocusrevisible 时,会重新发起请求。
  • API 释义
    • options.refreshOnWindowFocus 设置在浏览器窗口 refocusrevisible 时,重新发起请求。
      • 在 refocus 时,是否需要触发,会不会太频繁?
    • options.focusTimespan 设置重新请求间隔

Loading Delay

  const { loading } = useRequest(getCurrentTime, {
    loadingDelay: 200,
  });
  • 设置 options.loadingDelay ,可以延迟 loading 变成 true 的时间,有效防止闪烁。
  • API 释义
    • options.loadingDelay 设置 loading 变成 true 的延迟时间

ready

  const { data } = useRequest(getUserInfo, {
    ready: visible
  });

  const { loading } = useRequest(getContact, {
    ready: !!data
  });
  • API 释义
    • options.ready 🚩 只有 ready 变为 true 时,才会发起请求
      • 如果 manual=false,则在首次 readyfalse 变为 true 时,会自动执行
      • 通过 run 触发请求时,会先校验 ready,只有 ready=true,才会发起请求,否则会废弃该次请求。
  • 相关 issue:#977#727#468

缓存&SWR

  const { data, loading } = useRequest(getArticle, {
    cacheKey: 'article',
    cacheTime: '',
    staleTime: '',
    cacheType: 'localStorage' | 'sessionStorage' | 'memory',
    setCache: ()=>{},
    getCache: ()=>{},
  });
  • 设置 options.cacheKey 后,开启缓存模式,开启 SWR 特性,数据在全局同一个 cacheKey 下共享。
  • API 释义
    • options.cacheKey 🚩 代表请求的唯一 key
      • 如果设置了 cacheKey,数据会被存起来,下次请求时,会先返回缓存的数据,然后在背后发送新请求。
      • 同一个 key 的数据在全局共享
      • 同一个 key 的 Promise 在全局共享,也就是如果已经有在进行中的 Promise 了,新请求就会等待
    • options.cacheTime 设置数据缓存时间,默认不活跃 5 分钟后清空数据
      • 可以设置为 -1,表示永不过期
    • options.staleTime 设置数据新鲜时间,在该时间内,不会重新发请求
      • 可以设置为 -1,表示永远新鲜
    • options.cacheType 🚩 数据存储的地方,默认为 memory,支持存储到 localStorage 或 sessionStorage
      • 如果设置了 localStoragesessionStorage,则强制 cacheTime = -1,除非手动设置
    • options.setCache 🚩 options.getCache 🚩 自定义缓存读写方法
  • 其它
    • 如果本次请求失败,则不更新缓存数据
    • **manual=true**** 时如何处理缓存?**
  • 相关 issue:#950#931#930#834#764#723#593

mutate

const { data, mutate } = useRequest(getUsername, {
  onSuccess: (result) => {
    setState(result);
  },
});

mutate('hello');
  • API 释义
    • result.mutate 直接修改 data,同一个 cacheKey 都会被影响。
      • 常见场景为:编辑用户名称场景
        • 请求用户详情
        • 编辑用户详情,通过 mutate 立即生效,提升体验
        • 编辑成功后,重新请求用户详情,检查数据是否编辑成功

suspense

const { data } = useRequest(getUsername, {
  suspense: true,
});
  • API 释义
    • options.suspense 🚩 开启 suspense 模式
  • 相关 issue:#475

错误重试

const { data } = useRequest(getUsername, {
  retryInterval: 1000,
  retryCount: 3,
});
  • 如果设置了 options.retryCount,则启动错误重试。
    • options.retryCount 🚩 设置重试次数,如果设置为 -1,则无限重试
    • options.retryInterval 🚩 设置重置间隔,如果不设置,则采用指数退避算法

更多 Return

  • result.params 当次执行的 service 的参数数组。比如触发了 run(1, 2, 3),则 params 等于 [1, 2, 3]
  • result.cancel 取消当前请求、取消轮询、取消防抖、取消节流
  • result.refresh 使用上一次的 params,重新执行 service

更多 Options

  • options.refreshDeps 在 manual=false 时,refreshDeps 变化,会触发 service 重新执行。相当于下面写法的语法糖。
const [userId, setUserId] = useState('1');
const { data, run, loading } = useRequest(()=> getUserSchool(userId));
useEffect(() => {
  run();
}, [userId]);
  • options.formatResult 格式化请求结果,会影响 dataonSuccess
  • options.defaultParams 如果 manual=false,自动执行 run 的时候,默认带上的参数
  • options.onBefore 请求之前触发,参数为 (params)
  • options.onFinally 请求完成触发,参数为 (params, result, error)

删除的特性

  • options.initialData
    可以通过 const { data = [1]} = useRequest(xxx) 来设置初始值
  • useRequestProvinder
    建议自己基于 useRequest 封装一下就好,提供 demo
  • 不再内置 fetch,提供一个集成 fetch/axios 的 demo #674
  • pagination、loadmore 等不再支持,单独实现 hooks

clearCache

import {clearCache} from 'ahooks';

clearCache(); //清空所有缓存
clearCache(key); //删除特定缓存
  • 清空缓存 🚩
  • 相关 issue:#884

小程序环境支持

对 Taro、Remax 等跨端应用支持

  • options.documentVisibleCallback 🚩 支持配置屏幕可见时的回调函数,以支持 pollingWhenHidden 的正常表现

待考虑 issue

  • #971 希望useRequest能够提供一个配置支持拦截重复请求
  • #947 initialData 相关问题
  • #913 loading 设置最小间隔
  • #862 希望能够取消请求行为
  • #798 希望useRequest出一个onvisibilitychange版api
  • #759 debounceInterval 的 loading 时机调整
  • #607 给 useRequest 添加开始请求的钩子函数
@brickspert brickspert added the v3 label Sep 24, 2021
@brickspert brickspert self-assigned this Sep 24, 2021
@eightHundreds
Copy link

请问, throwOnError的意义是什么.

看源码它只做了2件事。

  1. console.log 异常
    2.将异常包装了下,再抛出

如果异常是直接throw的,如果没处理会抛到全局,浏览器控制台也是会显示的。
把异常包装下只能看出异常是来自useRequest,但它隐藏了异常细节,对监控系统不友好。

@brickspert
Copy link
Collaborator Author

请问, throwOnError的意义是什么.

看源码它只做了2件事。

  1. console.log 异常
    2.将异常包装了下,再抛出

如果异常是直接throw的,如果没处理会抛到全局,浏览器控制台也是会显示的。 把异常包装下只能看出异常是来自useRequest,但它隐藏了异常细节,对监控系统不友好。

3.0 版本已经没有这个属性了,会提供 run 和 runAsync 两个方法,run 默认捕获异常,runAsync 默认不捕获异常。

@over58
Copy link

over58 commented Nov 4, 2021

loadMore 和 run 同时存在的情况下,多次调用run, 只有首次才会有loading false ==> true ==> false 的过程,第二次以及以后调用loading始终为false, 反而一直是loadingMore经历false ==> true ==> false 的过程。其实调用run方法只能算首次加载,始终用的应该是loading

@AnaniZhu
Copy link

3.0 版本已经没有这个属性了,会提供 run 和 runAsync 两个方法,run 默认捕获异常,runAsync 默认不捕获异常。

useRequest@3.x 什么时候发布?

@brickspert
Copy link
Collaborator Author

3.0 版本已经没有这个属性了,会提供 run 和 runAsync 两个方法,run 默认捕获异常,runAsync 默认不捕获异常。

useRequest@3.x 什么时候发布?

现在已经可以用了,文档:https://ahooks-next.surge.sh/

@liuwei1025
Copy link

3.0版本是移除了useRequestready的支持吗

@brickspert
Copy link
Collaborator Author

3.0版本是移除了useRequestready的支持吗

暂时是的,还没想好 ready 要怎么做。后面想好了会加~

@GeraltX
Copy link

GeraltX commented Nov 22, 2021

所以 fetchKey 还有吗。没有的话,像表格组件,每一行都写一个 useRequest 会不会有问题?

@brickspert
Copy link
Collaborator Author

所以 fetchKey 还有吗。没有的话,像表格组件,每一行都写一个 useRequest 会不会有问题?

  1. fetchKey 没了。
  2. 不会有问题的。

@kongmoumou
Copy link
Contributor

所以 fetchKey 还有吗。没有的话,像表格组件,每一行都写一个 useRequest 会不会有问题?

  1. fetchKey 没了。
  2. 不会有问题的。

fetchKey 没了,动态并行请求有替代的解决方案嘛😁

@brickspert
Copy link
Collaborator Author

所以 fetchKey 还有吗。没有的话,像表格组件,每一行都写一个 useRequest 会不会有问题?

  1. fetchKey 没了。
  2. 不会有问题的。

fetchKey 没了,动态并行请求有替代的解决方案嘛😁

动态并行请求可以举个例子么。。

之前官网的 fetchKey demo,可以将删除按钮封装成一个组件解决。

@kongmoumou
Copy link
Contributor

kongmoumou commented Nov 30, 2021

动态并行请求可以举个例子么。。

动态生成的资源列表 [a, b, c, d] → 遍历列表同时请求 → 界面显示每个请求的状态与结果

v3 这种场景怎么处理比较好呢

@brickspert
Copy link
Collaborator Author

动态并行请求可以举个例子么。。

动态生成的资源列表 [a, b, c, d] → 遍历列表同时请求 → 界面显示每个请求的状态与结果

v3 这种场景怎么处理比较好呢

封装一个 Item 组件?请求逻辑放到每个 Item 中。

1 similar comment
@brickspert
Copy link
Collaborator Author

动态并行请求可以举个例子么。。

动态生成的资源列表 [a, b, c, d] → 遍历列表同时请求 → 界面显示每个请求的状态与结果

v3 这种场景怎么处理比较好呢

封装一个 Item 组件?请求逻辑放到每个 Item 中。

@kongmoumou
Copy link
Contributor

封装一个 Item 组件?请求逻辑放到每个 Item 中。

如果想在父组件统一管理请求状态呢😂

@brickspert
Copy link
Collaborator Author

如果想在父组件统一管理请求状态呢😂

那不支持了。。。

@GeraltX
Copy link

GeraltX commented Dec 6, 2021

忽然想到个问题,如果把请求状态放在子组件中处理,那如果父组件是虚拟滚动的列表,那子组件的请求状态就丢失了。

@eightHundreds
Copy link

eightHundreds commented Dec 16, 2021

请问, throwOnError的意义是什么.
看源码它只做了2件事。

  1. console.log 异常
    2.将异常包装了下,再抛出

如果异常是直接throw的,如果没处理会抛到全局,浏览器控制台也是会显示的。 把异常包装下只能看出异常是来自useRequest,但它隐藏了异常细节,对监控系统不友好。

3.0 版本已经没有这个属性了,会提供 run 和 runAsync 两个方法,run 默认捕获异常,runAsync 默认不捕获异常。

我想了解下在2.0中throwOnError 我全部设置为true,是不是没问题?应该不会影响到渲染而且抛出的异常内容会更精准?之前为什么考虑加这个功能?

@brickspert
Copy link
Collaborator Author

我想了解下在2.0中throwOnError 我全部设置为true,是不是没问题?应该不会影响到渲染而且抛出的异常内容会更精准?之前为什么考虑加这个功能?

  1. 不会影响到渲染而且抛出的异常内容会更精准
  2. 之前对异常的处理理解有问题,想一个 run 解决问题,但是不现实。 所以 3.0 提供了 run 和 runAsync

@dvlin-dev
Copy link

  1. 请问在ahooks v3中 useRequest 取消了请求库, 您在实际开发中使用的请求库是Fetch还是自己封装的xhr或封装好的axios,umi新版本准备丢弃umi-request 使用axios,是因为fetch有什么坑吗

@snowrain0722
Copy link

旧版的autoCancel属性为什么取消了,用什么做代替啊?

@liuyib
Copy link
Collaborator

liuyib commented Aug 7, 2023

旧版的autoCancel属性为什么取消了,用什么做代替啊?

具体哪个版本呢?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

10 participants