[ahooks] useRequest源码阅读(二)

上一节我们分析了useRequest核心的Fetch模块的原理,这一节我们来看它是怎么使用的

useRequest

我们先来看useRequest这个hooks,可以看到它调用了useRequestImplement,并传入三个参数: service, optionsplugins,这里可以看到内部的plugins优先级要高于外部传入的:

ts 复制代码
import useAutoRunPlugin from './plugins/useAutoRunPlugin';
import useCachePlugin from './plugins/useCachePlugin';
import useDebouncePlugin from './plugins/useDebouncePlugin';
import useLoadingDelayPlugin from './plugins/useLoadingDelayPlugin';
import usePollingPlugin from './plugins/usePollingPlugin';
import useRefreshOnWindowFocusPlugin from './plugins/useRefreshOnWindowFocusPlugin';
import useRetryPlugin from './plugins/useRetryPlugin';
import useThrottlePlugin from './plugins/useThrottlePlugin';
import type { Options, Plugin, Service } from './types';
import useRequestImplement from './useRequestImplement';

function useRequest<TData, TParams extends any[]>(
  service: Service<TData, TParams>,
  options?: Options<TData, TParams>,
  plugins?: Plugin<TData, TParams>[],
) {
  return useRequestImplement<TData, TParams>(service, options, [
    ...(plugins || []),
    useDebouncePlugin,
    useLoadingDelayPlugin,
    usePollingPlugin,
    useRefreshOnWindowFocusPlugin,
    useThrottlePlugin,
    useAutoRunPlugin,
    useCachePlugin,
    useRetryPlugin,
  ] as Plugin<TData, TParams>[]);
}

export default useRequest;

useRequestImplement

先是对传入的参数进行默认值的赋值,生成fetchOptions,然后调用new Fetch()方法生成fetchInstance实例,这里可以看到紧接着就是运行所有插件获取插件的返回值,然后赋值给Fetch实例的pluginImpls属性:

ts 复制代码
const fetchInstance = useCreation(() => { 
    const initState = plugins.map((p) => p?.onInit?.(fetchOptions)).filter(Boolean); 
    // Generation Fetch Instance
    return new Fetch<TData, TParams>( serviceRef, fetchOptions, update, Object.assign({}, ...initState), ); 
}, []); 
fetchInstance.options = fetchOptions;
// run all plugins hooks 
fetchInstance.pluginImpls = plugins.map((p) => p(fetchInstance, fetchOptions));

接下来是判断初始化时是否自动执行一次,如果条件满足,则在组件挂载时执行初始化参数并调用实例的run 方法

在组件卸载时执行cancel方法

最后是组件返回包括data在内的各个state和方法

ts 复制代码
import useCreation from '../../useCreation';
import useLatest from '../../useLatest';
import useMemoizedFn from '../../useMemoizedFn';
import useMount from '../../useMount';
import useUnmount from '../../useUnmount';
import useUpdate from '../../useUpdate';
import isDev from '../../utils/isDev';

import Fetch from './Fetch';
import type { Options, Plugin, Result, Service } from './types';

function useRequestImplement<TData, TParams extends any[]>(
  service: Service<TData, TParams>,
  options: Options<TData, TParams> = {},
  plugins: Plugin<TData, TParams>[] = [],
) {
  const { manual = false, ready = true, ...rest } = options;

  if (isDev) {
    if (options.defaultParams && !Array.isArray(options.defaultParams)) {
      console.warn(`expected defaultParams is array, got ${typeof options.defaultParams}`);
    }
  }

  const fetchOptions = {
    manual,
    ready,
    ...rest,
  };

  const serviceRef = useLatest(service);

  const update = useUpdate();

  const fetchInstance = useCreation(() => {
    const initState = plugins.map((p) => p?.onInit?.(fetchOptions)).filter(Boolean);

    return new Fetch<TData, TParams>(
      serviceRef,
      fetchOptions,
      update,
      Object.assign({}, ...initState),
    );
  }, []);
  fetchInstance.options = fetchOptions;
  // run all plugins hooks
  fetchInstance.pluginImpls = plugins.map((p) => p(fetchInstance, fetchOptions));

  useMount(() => {
    if (!manual && ready) {
      // useCachePlugin can set fetchInstance.state.params from cache when init
      const params = fetchInstance.state.params || options.defaultParams || [];
      // @ts-ignore
      fetchInstance.run(...params);
    }
  });

  useUnmount(() => {
    fetchInstance.cancel();
  });

  return {
    loading: fetchInstance.state.loading,
    data: fetchInstance.state.data,
    error: fetchInstance.state.error,
    params: fetchInstance.state.params || [],
    cancel: useMemoizedFn(fetchInstance.cancel.bind(fetchInstance)),
    refresh: useMemoizedFn(fetchInstance.refresh.bind(fetchInstance)),
    refreshAsync: useMemoizedFn(fetchInstance.refreshAsync.bind(fetchInstance)),
    run: useMemoizedFn(fetchInstance.run.bind(fetchInstance)),
    runAsync: useMemoizedFn(fetchInstance.runAsync.bind(fetchInstance)),
    mutate: useMemoizedFn(fetchInstance.mutate.bind(fetchInstance)),
  } as Result<TData, TParams>;
}

export default useRequestImplement;

总结

至此useRequest的核心执行流程便分析完了,随后会不定时补出各个插件的源码分析,感谢各位的阅读

相关推荐
mit6.8242 分钟前
[AI React Web] 包与依赖管理 | `axios`库 | `framer-motion`库
前端·人工智能·react.js
老虎06277 分钟前
JavaWeb前端(HTML,CSS具体案例)
前端·css·html
Mintopia12 分钟前
一个月速成 AI 工程师:从代码小白到智能工匠的修炼手册
前端·javascript·aigc
Mintopia16 分钟前
Next.js 全栈:接收和处理请求
前端·javascript·next.js
袁煦丞1 小时前
2025.8.18实验室【代码跑酷指南】Jupyter Notebook程序员的魔法本:cpolar内网穿透实验室第622个成功挑战
前端·程序员·远程工作
Joker Zxc1 小时前
【前端基础】flex布局中使用`justify-content`后,最后一行的布局问题
前端·css
无奈何杨1 小时前
风控系统事件分析中心,关联关系、排行、时间分布
前端·后端
Moment1 小时前
nginx 如何配置防止慢速攻击 🤔🤔🤔
前端·后端·nginx
晓得迷路了1 小时前
栗子前端技术周刊第 94 期 - React Native 0.81、jQuery 4.0.0 RC1、Bun v1.2.20...
前端·javascript·react.js