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

留言
avatar-img
留言分享你的想法!
avatar-img
s_SoNg的沙龍
4會員
11內容數
s_SoNg的沙龍的其他內容
2025/04/28
在工作上遇到nodejs呼叫執行檔執行失敗問題,最後發現是由於nodejs專案本身有用nssm包成服務,在服務環境的nodejs呼叫的執行檔也執行在服務中,造成程式不會跳出視窗而導致失敗。
Thumbnail
2025/04/28
在工作上遇到nodejs呼叫執行檔執行失敗問題,最後發現是由於nodejs專案本身有用nssm包成服務,在服務環境的nodejs呼叫的執行檔也執行在服務中,造成程式不會跳出視窗而導致失敗。
Thumbnail
2025/04/08
準備專案 這邊首先準備一個新的專案,可以參考react官網,完成後參考README.md輸入npm run dev就可以啟動並在瀏覽器看到畫面 準備nssm工具 在google上搜nssm,第一個項目點進去後,找到並下載穩定版,附上下載鏈接 壓縮檔下載完畢後,解壓縮到喜歡的地方,然後進入資料
Thumbnail
2025/04/08
準備專案 這邊首先準備一個新的專案,可以參考react官網,完成後參考README.md輸入npm run dev就可以啟動並在瀏覽器看到畫面 準備nssm工具 在google上搜nssm,第一個項目點進去後,找到並下載穩定版,附上下載鏈接 壓縮檔下載完畢後,解壓縮到喜歡的地方,然後進入資料
Thumbnail
2024/10/15
利用shapecast函式參與過濾的過程
Thumbnail
2024/10/15
利用shapecast函式參與過濾的過程
Thumbnail
看更多
你可能也想看
Thumbnail
TOMICA第一波推出吉伊卡哇聯名小車車的時候馬上就被搶購一空,一直很扼腕當時沒有趕緊入手。前陣子閒來無事逛蝦皮,突然發現幾家商場都又開始重新上架,價格也都回到正常水準,估計是官方又再補了一批貨,想都沒想就立刻下單! 同文也跟大家分享近期蝦皮購物紀錄、好用推薦、蝦皮分潤計畫的聯盟行銷!
Thumbnail
TOMICA第一波推出吉伊卡哇聯名小車車的時候馬上就被搶購一空,一直很扼腕當時沒有趕緊入手。前陣子閒來無事逛蝦皮,突然發現幾家商場都又開始重新上架,價格也都回到正常水準,估計是官方又再補了一批貨,想都沒想就立刻下單! 同文也跟大家分享近期蝦皮購物紀錄、好用推薦、蝦皮分潤計畫的聯盟行銷!
Thumbnail
每年4月、5月都是最多稅要繳的月份,當然大部份的人都是有機會繳到「綜合所得稅」,只是相當相當多人還不知道,原來繳給政府的稅!可以透過一些有活動的銀行信用卡或電子支付來繳,從繳費中賺一點點小確幸!就是賺個1%~2%大家也是很開心的,因為你們把沒回饋變成有回饋,就是用卡的最高境界 所得稅線上申報
Thumbnail
每年4月、5月都是最多稅要繳的月份,當然大部份的人都是有機會繳到「綜合所得稅」,只是相當相當多人還不知道,原來繳給政府的稅!可以透過一些有活動的銀行信用卡或電子支付來繳,從繳費中賺一點點小確幸!就是賺個1%~2%大家也是很開心的,因為你們把沒回饋變成有回饋,就是用卡的最高境界 所得稅線上申報
Thumbnail
這篇文章整理了前端開發中常見的效能優化技巧、React與JavaScript的知識點,以及Redux Toolkit和React Fiber的應用、Reflow與Repaint、Event Loop、Higher Order Component、React Hooks等主題。
Thumbnail
這篇文章整理了前端開發中常見的效能優化技巧、React與JavaScript的知識點,以及Redux Toolkit和React Fiber的應用、Reflow與Repaint、Event Loop、Higher Order Component、React Hooks等主題。
Thumbnail
任何語言特性用與不用,其實要看是否提升了生產力?是否提升可讀性?是否提升可維護性?這些都是在三個月甚至半年後回來修改程式時,才能明顯感受到的,而不是寫程式的當下。Java 8 的 CompletableFuture、Stream 和 Optional 都很好,但用的不好反而畫蛇添足又沒提高可讀性。
Thumbnail
任何語言特性用與不用,其實要看是否提升了生產力?是否提升可讀性?是否提升可維護性?這些都是在三個月甚至半年後回來修改程式時,才能明顯感受到的,而不是寫程式的當下。Java 8 的 CompletableFuture、Stream 和 Optional 都很好,但用的不好反而畫蛇添足又沒提高可讀性。
Thumbnail
接續上一篇文章,以留有餘裕的觀點來看,那當然是該早早開始,這樣才能一邊處理各種問題,一邊推進進度。但人性不是這樣,因為開始很困難,所以就不想去做。而飛輪效應這個理論告訴我們,要推動一個二噸重的飛輪當然很困難,一開始只能耗盡全身力氣還只能動一點點,但只要開始運轉起來之後,還可以持續運轉下去,只要再投入
Thumbnail
接續上一篇文章,以留有餘裕的觀點來看,那當然是該早早開始,這樣才能一邊處理各種問題,一邊推進進度。但人性不是這樣,因為開始很困難,所以就不想去做。而飛輪效應這個理論告訴我們,要推動一個二噸重的飛輪當然很困難,一開始只能耗盡全身力氣還只能動一點點,但只要開始運轉起來之後,還可以持續運轉下去,只要再投入
Thumbnail
藍色系應該就做到這裡了,畢竟太多也是會審美疲勞的。
Thumbnail
藍色系應該就做到這裡了,畢竟太多也是會審美疲勞的。
Thumbnail
這是 30 天寫作挑戰的第 02 天。今天 ChatGPT 問我的問題是: 在你的開發流程中,你如何處理產品需求的變更或優先級的調整?
Thumbnail
這是 30 天寫作挑戰的第 02 天。今天 ChatGPT 問我的問題是: 在你的開發流程中,你如何處理產品需求的變更或優先級的調整?
Thumbnail
這篇文章將會快速介紹非同步函式(Async / Await)的簡易使用方式。
Thumbnail
這篇文章將會快速介紹非同步函式(Async / Await)的簡易使用方式。
Thumbnail
只要在軟體公司待過,一定對於敏捷式開發不陌生,在現在的年代,是一種頗為主流的開發方式,這種開發方式,有著開發期短、彈性大、持續迭代的特性,但有時候不免會帶來一些技術債、版本管理的問題。 反正只要有了問題,只要快速的修正、並且上新版本去調整即可。 "難道不可以同時進行嗎?" 這樣,真的有比較快嗎?
Thumbnail
只要在軟體公司待過,一定對於敏捷式開發不陌生,在現在的年代,是一種頗為主流的開發方式,這種開發方式,有著開發期短、彈性大、持續迭代的特性,但有時候不免會帶來一些技術債、版本管理的問題。 反正只要有了問題,只要快速的修正、並且上新版本去調整即可。 "難道不可以同時進行嗎?" 這樣,真的有比較快嗎?
Thumbnail
因為明天必須要早起出門辦事情,擔心沒辦法可以在早上寫作完畢,就在晚上直接超前部署把明天的挑戰先做完XD 日期:7/8 閱讀時間:19:30 - 20:00 製圖時間:20:00 - 20:20 閱讀書籍:提案一次就過的技術 本篇的寫作方式,採用圖解 我把本書第一章的內容,直接轉
Thumbnail
因為明天必須要早起出門辦事情,擔心沒辦法可以在早上寫作完畢,就在晚上直接超前部署把明天的挑戰先做完XD 日期:7/8 閱讀時間:19:30 - 20:00 製圖時間:20:00 - 20:20 閱讀書籍:提案一次就過的技術 本篇的寫作方式,採用圖解 我把本書第一章的內容,直接轉
Thumbnail
正在執行開發的進度,往往是還沒解決這個又來下一個,頓時覺得人生怎麼不是樸實無華,而是好難。
Thumbnail
正在執行開發的進度,往往是還沒解決這個又來下一個,頓時覺得人生怎麼不是樸實無華,而是好難。
追蹤感興趣的內容從 Google News 追蹤更多 vocus 的最新精選內容追蹤 Google News