await React setState的方法

閱讀時間約 5 分鐘

如果有個算法是2秒以上很耗時的長任務,希望在執行長任務前後修改state渲染loading畫面,可能會難以達到預期效果,會看到loading畫面一閃而過。

setLoading(true);
longTask();
setLoading(false);

因為React在setstate後狀態不會馬上改變與渲染,如果後面緊跟一個長任務,長任務會馬上佔用所有資源,直到結束後才改變狀態與渲染。

把setState改非同步的方法

實現的思路是在setState時建立一個Promise,然後useEffect監聽到狀態改變後呼叫這個Promise的resolve方法,直接上程式碼。

const Main = () => {
  const [spinning, setSpinning] = useState(false);

// 防止useEffect取到的spinning和setSpinningAsync裡取到的不同
  const spinningStateRef = useRef(false);
// 儲存Promise的resolve方法
  const spinningResolveRef = useRef(() => {});

  const setSpinningAsync = (isSpinning) => {
// 先呼叫與清空上次的resolve,避免有地方程式被await卡住
    spinningResolveRef.current();
    spinningResolveRef.current = () => {};

    const currentLoadingState = spinningStateRef.current;
    if (isSpinning == currentLoadingState) return;

    return new Promise((resolve) => {
      setSpinning(isSpinning);
// setState後儲存這次Promise的resolve
      spinningResolveRef.current = resolve;
    });
  };

  useEffect(() => {
    const updateSpinningRef = async () => {
// 如果電腦很卡,可以多設些緩衝時間確保畫面已渲染
      await new Promise((resolve) => setTimeout(resolve, 100));
// 確保狀態已改變,畫面已渲染,就呼叫resolve(),讓executWithAsync函式await的程式繼續
      spinningResolveRef.current();
      spinningStateRef.current = spinning;
    };

    updateSpinningRef();
  }, [spinning]);

  const executWithAsync = async () => {
    await setSpinningAsync(true);
    longSyncTask(2000);
    await setSpinningAsync(false);
  };

  return (
    <Spin spinning={spinning}>
      <Button onClick={executWithAsync}>Wait until spinning</Button>
    </Spin>
  );
};

最後附上完整demo: await useState demo

內容總結
React await setStat
4
/5
4會員
9內容數
留言0
查看全部
發表第一個留言支持創作者!
s_SoNg的沙龍 的其他內容
利用shapecast函式參與過濾的過程
bvh是一種樹狀結構,會為模型建立很多層由大到小的包圍框 常用來加速尋找符合條件的網格,可快速判斷是否與另一個模型相交、快速找最近點等 本文會簡單介紹用Three-mesh-bvh套件快速判斷兩個模型是否相交的原理
在網路速度有限的情況下,依序記錄不斷產生的資訊,能統計使用者在頁面上操作了哪些功能。
ThreeJS ArcballControl呼叫update方法後,視角被翻轉問題的解決記錄
setter和getter能把狀態改變時需做的事情包裝起來,讓外部只需簡單修改參數就能達到預想的效果
在程式任何地方都能修改各種react組件狀態的做法分享
利用shapecast函式參與過濾的過程
bvh是一種樹狀結構,會為模型建立很多層由大到小的包圍框 常用來加速尋找符合條件的網格,可快速判斷是否與另一個模型相交、快速找最近點等 本文會簡單介紹用Three-mesh-bvh套件快速判斷兩個模型是否相交的原理
在網路速度有限的情況下,依序記錄不斷產生的資訊,能統計使用者在頁面上操作了哪些功能。
ThreeJS ArcballControl呼叫update方法後,視角被翻轉問題的解決記錄
setter和getter能把狀態改變時需做的事情包裝起來,讓外部只需簡單修改參數就能達到預想的效果
在程式任何地方都能修改各種react組件狀態的做法分享
你可能也想看
Google News 追蹤
Thumbnail
接下來第二部分我們持續討論美國總統大選如何佈局, 以及選前一週到年底的操作策略建議 分析兩位候選人政策利多/ 利空的板塊和股票
Thumbnail
🤔為什麼團長的能力是死亡筆記本? 🤔為什麼像是死亡筆記本呢? 🤨作者巧思-讓妮翁死亡合理的幾個伏筆
Thumbnail
切換頁面卡卡有很多種原因,這裡舉的例子只針對元件太大的情境。 除了想辦法拆分外,還有一個方法就是利用 Vue 的 Async Component。
Thumbnail
本文介紹了在網站開發中如何運用狀態機的原則和設計方法。通過具體案例分析,以及狀態和數據的區分,詳細介紹了狀態機的設計原則和應用。讀者可以通過本文瞭解如何將狀態機應用於實際的網站開發中。
Thumbnail
在網路速度有限的情況下,依序記錄不斷產生的資訊,能統計使用者在頁面上操作了哪些功能。
Thumbnail
分享一個有趣的套件,名為 await-to-js。 可以讓 Promise 與 await 的寫法更簡潔。
Thumbnail
需求情境: 在設計畫面時,資料來源是後台的 api,每一次畫面細節的修修改改,都會觸發 Xcode Preview 程序,導致不斷呼叫後台。此時若資料結構和大小都具有一定規模,就會導致效率低落,不斷等待,且消耗伺服器資源甚鉅。 解決方案: 將後台傳回的資料以檔案形式暫存在本地端,每次 pr
Thumbnail
更快、更短、更即時是串流傳輸必要的元素, 而我們常常在使用Python請求API時都是等待式回應, 也就是一個請求過去之後, 待對方處理完畢後再行回應, 但假設需要下載的檔案、內容非常大時, 是不是使用者只能傻傻的等待整個傳輸結束後才能顯示? 這樣的使用者體驗也實在太糟糕了, 對於使用者來說除了完全
setter和getter能把狀態改變時需做的事情包裝起來,讓外部只需簡單修改參數就能達到預想的效果
Thumbnail
非同步程式設計(Asynchronous programming) 或是簡單的稱之為 async,它是一種並發程式模型(concurrent programming model),其目的就是讓多個任務能同時在作業系統的執行緒上執行,並透過 async/.await 保留同步。
Thumbnail
接下來第二部分我們持續討論美國總統大選如何佈局, 以及選前一週到年底的操作策略建議 分析兩位候選人政策利多/ 利空的板塊和股票
Thumbnail
🤔為什麼團長的能力是死亡筆記本? 🤔為什麼像是死亡筆記本呢? 🤨作者巧思-讓妮翁死亡合理的幾個伏筆
Thumbnail
切換頁面卡卡有很多種原因,這裡舉的例子只針對元件太大的情境。 除了想辦法拆分外,還有一個方法就是利用 Vue 的 Async Component。
Thumbnail
本文介紹了在網站開發中如何運用狀態機的原則和設計方法。通過具體案例分析,以及狀態和數據的區分,詳細介紹了狀態機的設計原則和應用。讀者可以通過本文瞭解如何將狀態機應用於實際的網站開發中。
Thumbnail
在網路速度有限的情況下,依序記錄不斷產生的資訊,能統計使用者在頁面上操作了哪些功能。
Thumbnail
分享一個有趣的套件,名為 await-to-js。 可以讓 Promise 與 await 的寫法更簡潔。
Thumbnail
需求情境: 在設計畫面時,資料來源是後台的 api,每一次畫面細節的修修改改,都會觸發 Xcode Preview 程序,導致不斷呼叫後台。此時若資料結構和大小都具有一定規模,就會導致效率低落,不斷等待,且消耗伺服器資源甚鉅。 解決方案: 將後台傳回的資料以檔案形式暫存在本地端,每次 pr
Thumbnail
更快、更短、更即時是串流傳輸必要的元素, 而我們常常在使用Python請求API時都是等待式回應, 也就是一個請求過去之後, 待對方處理完畢後再行回應, 但假設需要下載的檔案、內容非常大時, 是不是使用者只能傻傻的等待整個傳輸結束後才能顯示? 這樣的使用者體驗也實在太糟糕了, 對於使用者來說除了完全
setter和getter能把狀態改變時需做的事情包裝起來,讓外部只需簡單修改參數就能達到預想的效果
Thumbnail
非同步程式設計(Asynchronous programming) 或是簡單的稱之為 async,它是一種並發程式模型(concurrent programming model),其目的就是讓多個任務能同時在作業系統的執行緒上執行,並透過 async/.await 保留同步。