[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的核心执行流程便分析完了,随后会不定时补出各个插件的源码分析,感谢各位的阅读

相关推荐
鹏多多1 分钟前
用useTransition解决React性能卡顿问题+实战例子
前端·javascript·react.js
只愿云淡风清11 分钟前
ECharts地图数据压缩-ZigZag算法
前端·javascript·echarts
亿元程序员19 分钟前
都2025年了,还有面试问A*寻路的???
前端
Moment19 分钟前
Node.js v25.0.0 发布——性能、Web 标准与安全性全面升级 🚀🚀🚀
前端·javascript·后端
杨超越luckly24 分钟前
HTML应用指南:利用POST请求获取中国一汽红旗门店位置信息
前端·arcgis·html·数据可视化·门店数据
专注前端30年28 分钟前
【JavaScript】every 方法的详解与实战
开发语言·前端·javascript
速易达网络31 分钟前
Java Web登录系统实现(不使用开发工具)
java·开发语言·前端
IT_陈寒33 分钟前
Vite 3.0 性能优化实战:5个技巧让你的构建速度提升200% 🚀
前端·人工智能·后端
金士顿36 分钟前
EC-Engineer SDK 核心 API 使用指南
前端