在寫業務的過程當中,咱們老是會遇到這樣的需求,在請求時顯示一個 loading,而後請求結束後展現數據。以一個是否是 vip 的場景爲例,若是不加入 loading 狀態,頁面可能在未請求的時候顯示非 vip,數據請求完成以後,發現是 vip,再改爲 vip。這樣無疑體驗較差,可是咱們又不但願一直使用 useState 來聲明 loading 狀態,這無疑是乏味的:react
const [loading, setLoading] = useState(false); ...
因此,不如使用 hooks 來封裝這部分邏輯,來實現一個 useLoading hook。ajax
在寫這個 hook 以前,咱們要先理清楚這個 hook 的入參和出參。咱們但願這個 hook 有這樣的效果,咱們傳入一個請求的函數,獲得這個函數是否在 loading,以及一個包裝後的請求函數。代碼以下:api
const [isLoading, wrappedAjax] = useLoading(ajax);
直接上代碼:app
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。調用方式以下:ide
const [loading, req] = useLoading(checkVip); useEffect(() => { req().then(({ vip }) => { console.log(vip); setVip(vip); }).catch((err) => alert(err)); }, [req]);
下面是一個簡單的 demo(沒看到效果請點擊刷新按鈕)。能夠看到,當不設置 loading 狀態的時候,頁面是由 no vip 跳到 vip 的,體驗是比較差的。函數
當咱們只是須要一個 loading 狀態,而又不想寫重複的 useState 來管理 loading 狀態時,上面這個小 hook 就顯得更輕量了。可是若是須要一整套完整的解決方案,使用 React Query 則是更好的選擇。(本文完)spa