91超碰碰碰碰久久久久久综合_超碰av人澡人澡人澡人澡人掠_国产黄大片在线观看画质优化_txt小说免费全本

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

ahooks?useRequest怎么使用

發布時間:2023-03-09 16:27:46 來源:億速云 閱讀:245 作者:iii 欄目:開發技術

這篇文章主要介紹“ahooks useRequest怎么使用”,在日常操作中,相信很多人在ahooks useRequest怎么使用問題上存在疑惑,小編查閱了各式資料,整理出簡單好用的操作方法,希望對大家解答”ahooks useRequest怎么使用”的疑惑有所幫助!接下來,請跟著小編一起來學習吧!

基礎版(雛形)

先上代碼:

useRequest.ts

interface UseRequestOptionsProps {
  /*
   * 請求參數
   */
  initialData?: object;
  /*
   * 請求成功回調
   */
  onSuccess?: (res: any) => void;
}
const useRequest = (
  requestFn: (
    initialData?: object | string | [],
  ) => Promise<SetStateAction<any>>,
  options: UseRequestOptionsProps,
) => {
  const [data, setData] = useState<SetStateAction<any>>(null);
  const [loading, setLoading] = useState<boolean>(false);
  const [error, setError] = useState<string | null>(null);
  const { initialData, onSuccess } = options;
  useEffect(() => {
    setLoading(true);
    setError(null);
    setData(null);
    request();
  }, [requestFn]);
  // useRequest業務邏輯
  const request = async () => {
    try {
      const res = await requestFn(initialData);
      setData(res);
      // 請求成功響應回調
      onSuccess && onSuccess(res);
    } catch (err) {
      err && setError(JSON.stringify(err));
    } finally {
      setLoading(false);
    }
  };
  return { data, loading, error };
};
export default useRequest;

使用

const { data, loading, error } = useRequest(
    queryCompensatoryOrderSituation,
    {
        initialData: {
            compensatoryId,
        }
        onSuccess: (res) => {
            console.log('success request!', res);
        },
    },
);

useRequest 對于請求函數的寫法并無過多要求,只要是一個異步function且返回一個promise對象,即可傳入useRequest的第一個參數中,而第二個參數則是一系列的可選配置項,雛形版本我們暫時只支持onSuccess

手動觸發

代碼改造后:

useRequest.ts

interface UseRequestOptionsProps {
  /*
   * 手動開啟
   */
  manual?: boolean;
  /*
   * 請求參數
   */
  initialData?: object;
  /*
   * 請求成功回調
   */
  onSuccess?: (res: any) => void;
}
const useRequest = (
  requestFn: (
    initialData?: object | string | [],
  ) => Promise<SetStateAction<any>>,
  options: UseRequestOptionsProps,
) => {
  const [data, setData] = useState<SetStateAction<any>>(null);
  const [loading, setLoading] = useState<boolean>(false);
  const [error, setError] = useState<string | null>(null);
  const { manual, initialData, onSuccess } = options;
  useEffect(() => {
    setLoading(true);
    setError(null);
    setData(null);
    !manual && request();
  }, [manual]);
  // useRequest業務邏輯
  const request = async () => {
    try {
      const res = await requestFn(initialData);
      setData(res);
      // 請求成功響應回調
      onSuccess && onSuccess(res);
    } catch (err) {
      err && setError(JSON.stringify(err));
    } finally {
      setLoading(false);
    }
  };
  return { data, loading, error, request };
};
export default useRequest;

使用

const { data, loading, error, request } = useRequest(
    queryCompensatoryOrderSituation,
    {
        manual: true,
        initialData: {
            compensatoryId,
        },
        onSuccess: (res) => {
            console.log('success request!', res);
        },
    },
);
request();

手動執行的邏輯主要是根據manual參數砍掉useRequest mount階段的渲染請求,把執行請求的能力暴露出去,在頁面中去手動調用request()來觸發。

輪詢與手動取消

代碼改造后:

useRequest.ts

interface UseRequestOptionsProps {
  /*
   * 手動開啟
   */
  manual?: boolean;
  /*
   * 請求參數
   */
  initialData?: object;
  /*
   * 輪詢
   */
  pollingInterval?: number | null;
  /*
   * 請求成功回調
   */
  onSuccess?: (res: any) => void;
}
const useRequest = (
  requestFn: (
    initialData?: object | string | [],
  ) => Promise<SetStateAction<any>>,
  options: UseRequestOptionsProps,
) => {
  const [data, setData] = useState<SetStateAction<any>>(null);
  const [loading, setLoading] = useState<boolean>(false);
  const [error, setError] = useState<string | null>(null);
  const status = useRef<boolean>(false);
  const pollingIntervalTimer = useRef<NodeJS.Timer | null>(null);
  const { manual, initialData, pollingInterval, onSuccess } = options;
  useEffect(() => {
    setLoading(true);
    setError(null);
    setData(null);
    !manual && request();
  }, [manual]);
  // useRequest業務邏輯
  const request = async () => {
   try {
      !status.current && (status.current = true);
      if (pollingInterval && status.current) {
        pollingIntervalTimer.current = setTimeout(() => {
          status.current && request();
        }, pollingInterval);
      }
      const res = await requestFn(initialData);
      setData(res);
      // 請求成功響應回調
      onSuccess && onSuccess(res);
    } catch (err) {
      err && setError(JSON.stringify(err));
    } finally {
      setLoading(false);
    }
  };
  return { data, loading, error, request, cancel };
};
// 取消
const cancel = () => {
  if (pollingIntervalTimer.current) {
    clearTimeout(pollingIntervalTimer.current);
    pollingIntervalTimer.current = null;
    status.current && (status.current = false);
  }
};
export default useRequest;

使用

const { data, loading, error, request, cancel } = useRequest(
    queryCompensatoryOrderSituation,
    {
        manual: true,
        initialData: {
            compensatoryId,
        },
        pollingInterval: 1000,
        onSuccess: (res) => {
            console.log('success request!', res);
        },
    },
);
request();
...
// 輪詢到理想數據后
cancel();

輪詢的支持在hook中主要用到了timer setTimeout的遞歸思路,同時給出一個status狀態值判斷是否在輪詢中,當調用端執行cancel()status則為false;當輪詢開始,則statustrue

cancel()的能力 主要也是取消了timer的遞歸請求邏輯,并且輪詢的業務場景和manual: true配合很多。

依賴請求(串型請求)

代碼改造后:

useRequest.ts

interface UseRequestOptionsProps {
  /*
   * 手動開啟
   */
  manual?: boolean;
  /*
   * 請求參數
   */
  initialData?: object;
  /*
   * 輪詢
   */
  pollingInterval?: number | null;
  /*
   * 準備,用于依賴請求
   */
  ready?: boolean;
  /*
   * 請求成功回調
   */
  onSuccess?: (res: any) => void;
}
const useRequest = (
  requestFn: (
    initialData?: object | string | [],
  ) => Promise<SetStateAction<any>>,
  options: UseRequestOptionsProps,
) => {
  const [data, setData] = useState<SetStateAction<any>>(null);
  const [loading, setLoading] = useState<boolean>(false);
  const [error, setError] = useState<string | null>(null);
  const status = useRef<boolean>(false);
  const pollingIntervalTimer = useRef<NodeJS.Timer | null>(null);
  const {
    manual,
    initialData,
    pollingInterval,
    ready = true,
    onSuccess,
  } = options;
  useEffect(() => {
    setLoading(true);
    setError(null);
    setData(null);
    !manual && ready && request();
  }, [manual, ready]);
  // useRequest業務邏輯
  const request = async () => {
   try {
      !status.current && (status.current = true);
      if (pollingInterval && status.current) {
        pollingIntervalTimer.current = setTimeout(() => {
          status.current && request();
        }, pollingInterval);
      }
      const res = await requestFn(initialData);
      setData(res);
      // 請求成功響應回調
      onSuccess && onSuccess(res);
    } catch (err) {
      err && setError(JSON.stringify(err));
    } finally {
      setLoading(false);
    }
  };
  return { data, loading, error, request, cancel };
};
// 取消
const cancel = () => {
  if (pollingIntervalTimer.current) {
    clearTimeout(pollingIntervalTimer.current);
    pollingIntervalTimer.current = null;
    status.current && (status.current = false);
  }
};
export default useRequest;

使用

const [mountLoading, setMountLoading] = useState<boolean>(false);
useEffect(() => {
    setMountLoading(true);
}, [2000])
const { data, loading, error, request, cancel } = useRequest(
    queryCompensatoryOrderSituation,
    {
        initialData: {
            compensatoryId,
        },
        pollingInterval: 1000,
        ready: mountLoading,
        onSuccess: (res) => {
            console.log('success request!', res);
        },
    },
);

依賴請求的思路就是在hook中加入一個ready字段,也是在基于manual一層的限制后又加了一層,來判斷是否在hook加載時是否做默認請求,而當option中的ready更新(為true)時,hook自動更新從而發起請求。

常用于頁面中A請求完成后執行B請求,B請求的ready字段依賴于A請求的data/loading字段。

防抖與節流

防抖和節流的實現比較簡單,依賴于lodash庫,包裝了一下request函數的請求內容。

代碼如下:

useRequest.ts

interface UseRequestOptionsProps {
  /*
   * 手動開啟
   */
  manual?: boolean;
  /*
   * 請求參數
   */
  initialData?: object;
  /*
   * 輪詢
   */
  pollingInterval?: number | null;
  /*
   * 準備,用于依賴請求
   */
  ready?: boolean;
  /*
   * 防抖
   */
  debounceInterval?: number;
  /*
   * 節流
   */
  throttleInterval?: number;
  /*
   * 請求成功回調
   */
  onSuccess?: (res: any) => void;
}
const useRequest = (
  requestFn: (
    initialData?: object | string | [],
  ) => Promise<SetStateAction<any>>,
  options: UseRequestOptionsProps,
) => {
  const [data, setData] = useState<SetStateAction<any>>(null);
  const [loading, setLoading] = useState<boolean>(false);
  const [error, setError] = useState<string | null>(null);
  const status = useRef<boolean>(false);
  const pollingIntervalTimer = useRef<NodeJS.Timer | null>(null);
  const {
    manual,
    initialData,
    pollingInterval,
    ready = true,
    debounceInterval,
    throttleInterval
    onSuccess,
  } = options;
  useEffect(() => {
    setLoading(true);
    setError(null);
    setData(null);
    !manual && ready && request();
  }, [manual, ready]);
 //  請求
 const request = () => {
  if (debounceInterval) {
    lodash.debounce(requestDoing, debounceInterval)();
  } else if (throttleInterval) {
    lodash.throttle(requestDoing, throttleInterval)();
  } else {
    requestDoing();
  }
};
// useRequest業務邏輯
const requestDoing = async () => {
  try {
    !status.current && (status.current = true);
    if (pollingInterval && status.current) {
      pollingIntervalTimer.current = setTimeout(() => {
        status.current && request();
      }, pollingInterval);
    }
    const res = await requestFn(initialData);
    setData(res);
    // 請求成功響應回調
    onSuccess && onSuccess(res);
  } catch (err) {
    err && setError(JSON.stringify(err));
  } finally {
    setLoading(false);
  }
};
// 取消
const cancel = () => {
  if (pollingIntervalTimer.current) {
    clearTimeout(pollingIntervalTimer.current);
    pollingIntervalTimer.current = null;
    status.current && (status.current = false);
  }
};
export default useRequest;

使用

const { data, loading, error, request, cancel } = useRequest(
    queryCompensatoryOrderSituation,
    {
        manual: true,
        initialData: {
            compensatoryId,
        },
        debounceInterval: 1000,     // 防抖
        throttleInterval: 1000,     // 節流
        onSuccess: (res) => {
            console.log('success request!', res);
        },
    },
);
for(let i = 0; i < 10000; i++) {
    request();
}

hook中,通過lodash.debounce/lodash.throttle來包裝request函數主體,通過option中的判斷來執行對應的包裝體函數。

緩存與依賴更新

改造后的代碼(最終代碼)如下:

useRequest.ts

import {
  useState,
  useEffect,
  useRef,
  SetStateAction,
  useCallback,
} from 'react';
import lodash from 'lodash';
interface UseRequestOptionsProps {
  /*
   * 手動開啟
   */
  manual?: boolean;
  /*
   * 請求參數
   */
  initialData?: object;
  /*
   * 輪詢
   */
  pollingInterval?: number | null;
  /*
   * 準備,用于依賴請求
   */
  ready?: boolean;
  /*
   * 防抖
   */
  debounceInterval?: number;
  /*
   * 節流
   */
  throttleInterval?: number;
  /*
   * 延遲loading為true的時間
   */
  loadingDelay?: number;
  /*
   * 依賴
   */
  refreshDeps?: any[];
  /*
   * 請求成功回調
   */
  onSuccess?: (res: any) => void;
}
const useRequest = (
  requestFn: (
    initialData?: object | string | [],
  ) => Promise<SetStateAction<any>>,
  options: UseRequestOptionsProps,
) => {
  const [data, setData] = useState<SetStateAction<any>>(null);
  const [loading, setLoading] = useState<boolean>(false);
  const [error, setError] = useState<string | null>(null);
  const status = useRef<boolean>(false);
  const pollingIntervalTimer = useRef<NodeJS.Timer | null>(null);
  const {
    manual,
    initialData,
    pollingInterval,
    ready = true,
    debounceInterval,
    throttleInterval,
    loadingDelay,
    refreshDeps,
    onSuccess,
  } = options;
  useEffect(() => {
    if (loadingDelay) {
      setTimeout(() => {
        status && setLoading(true);
      }, loadingDelay);
    }
    setError(null);
    setData(null);
    // 手動觸發request
    !manual && ready && request();
  }, [manual, ready, ...(Array.isArray(refreshDeps) ? refreshDeps : [])]);
  //  請求
  const request = () => {
    if (debounceInterval) {
      lodash.debounce(requestDoing, debounceInterval)();
    } else if (throttleInterval) {
      lodash.throttle(requestDoing, throttleInterval)();
    } else {
      requestDoing();
    }
  };
  // useRequest業務邏輯
  const requestDoing = async () => {
    try {
      !status.current && (status.current = true);
      if (pollingInterval && status.current) {
        pollingIntervalTimer.current = setTimeout(() => {
          status.current && request();
        }, pollingInterval);
      }
      const res = await requestFn(initialData);
      setData(res);
      // 請求成功響應回調
      onSuccess && onSuccess(res);
    } catch (err) {
      err && setError(JSON.stringify(err));
    } finally {
      setLoading(false);
    }
  };
  // 取消
  const cancel = () => {
    if (pollingIntervalTimer.current) {
      clearTimeout(pollingIntervalTimer.current);
      pollingIntervalTimer.current = null;
      status.current && (status.current = false);
    }
  };
  // 緩存
  const cachedFetchData = useCallback(() => data, [data]);
  return { data, loading, error, request, cancel, cachedFetchData };
};
export default useRequest;

使用

const [mountLoading, setMountLoading] = useState<boolean>(false);
const [updateLoading, setUpdateLoading] = useState<boolean>(false);
setTimeout(() => {
    setMountLoading(true);
}, 1000);
setTimeout(() => {
    setUpdateLoading(true);
}, 2000);
const { data, loading, error, request, cancel, cachedFetchData } = useRequest(
    queryCompensatoryOrderSituation,
    {
        manual: true,
        initialData: {
            compensatoryId,
        },
        debounceInterval: 1000,     // 防抖
        throttleInterval: 1000,     // 節流
        refreshDeps: [mountLoading, updateLoading],
        onSuccess: (res) => {
            console.log('success request!', res);
        },
    },
);

緩存的主體思路是在useRequest中拿到第一次數據后通過useCallback來透出data依賴來保存,同時向外暴露一個cachedFetchData來過渡datanull到請求到接口數據的過程。

依賴更新的思路則是在頁面中給useRequest一系列依賴狀態一并加入在hook的請求副作用中,監聽到頁面中依賴改變,則重新請求,具體實現則是refreshDeps參數。

到此,關于“ahooks useRequest怎么使用”的學習就結束了,希望能夠解決大家的疑惑。理論與實踐的搭配能更好的幫助大家學習,快去試試吧!若想繼續學習更多相關知識,請繼續關注億速云網站,小編會繼續努力為大家帶來更多實用的文章!

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

厦门市| 锡林郭勒盟| 乡城县| 涟水县| 太湖县| 长子县| 原平市| 绥江县| 泰宁县| 宜章县| 诏安县| 临沂市| 玉山县| 齐齐哈尔市| 佳木斯市| 手机| 许昌市| 抚松县| 铜陵市| 成武县| 佛坪县| 旬阳县| 井陉县| 磴口县| 徐水县| 宝坻区| 亚东县| 宣威市| 广南县| 连州市| 夏河县| 丹巴县| 永丰县| 桃园市| 北碚区| 汤原县| 武功县| 扬中市| 云安县| 广平县| 大余县|