寫一個react hook:useLoading

飯特稠發表於2021-01-10

在寫業務的過程中,我們總是會遇到這樣的需求,在請求時顯示一個 loading,然後請求結束後展示資料。以一個是不是 vip 的場景為例,如果不加入 loading 狀態,頁面可能在未請求的時候顯示非 vip,資料請求完成之後,發現是 vip,再改成 vip。這樣無疑體驗較差,但是我們又不希望一直使用 useState 來宣告 loading 狀態,這無疑是乏味的:

const [loading, setLoading] = useState(false);
...

所以,不如使用 hooks 來封裝這部分邏輯,來實現一個 useLoading hook。

在寫這個 hook 之前,我們要先理清楚這個 hook 的入參和出參。我們希望這個 hook 有這樣的效果,我們傳入一個請求的函式,得到這個函式是否在 loading,以及一個包裝後的請求函式。程式碼如下:

const [isLoading, wrappedAjax] = useLoading(ajax);

實現

直接上程式碼:

import { useState, useCallback } from "react";
export default function useLoading(req) {
  const [loading, setLoading] = useState(false);
  const wrapReq = useCallback(
    (...args) => {
      setLoading(true);
      return req(...args).then((data) => {
        setLoading(false);
        return Promise.resolve(data);
      }).catch((reason) => {
      	setLoading(false);
        return Promise.reject(reason);
      });
    },
    [req]
  );
  return [loading, wrapReq];
}

程式碼也很簡單,就是對原先的 api 請求進行了包裝,在呼叫前,設定 loading 為 true,拿到資料之後,設定 loading 為 false。呼叫方式如下:

  const [loading, req] = useLoading(checkVip);
  useEffect(() => {
    req().then(({ vip }) => {
      console.log(vip);
      setVip(vip);
    }).catch((err) => alert(err));
  }, [req]);

下面是一個簡單的 demo(沒看到效果請點選重新整理按鈕)。可以看到,當不設定 loading 狀態的時候,頁面是由 no vip 跳到 vip 的,體驗是比較差的。

why not React Query

當我們只是需要一個 loading 狀態,而又不想寫重複的 useState 來管理 loading 狀態時,上面這個小 hook 就顯得更輕量了。但是如果需要一整套完整的解決方案,使用 React Query 則是更好的選擇。(本文完)

相關文章