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會員
12內容數
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
透過蝦皮分潤計畫,輕鬆賺取零用金!本文分享5-6月實測心得,包含數據流程、實際收入、平臺優點及注意事項,並推薦高分潤商品,教你如何運用空閒時間創造被動收入。
Thumbnail
透過蝦皮分潤計畫,輕鬆賺取零用金!本文分享5-6月實測心得,包含數據流程、實際收入、平臺優點及注意事項,並推薦高分潤商品,教你如何運用空閒時間創造被動收入。
Thumbnail
單身的人有些會養寵物,而我養植物。畢竟寵物離世會傷心,植物沒養好再接再厲就好了~(笑)
Thumbnail
單身的人有些會養寵物,而我養植物。畢竟寵物離世會傷心,植物沒養好再接再厲就好了~(笑)
Thumbnail
不知你有沒有過這種經驗?衛生紙只剩最後一包、洗衣精倒不出來,或電池突然沒電。這次一次補貨,從電池、衛生紙到洗衣精,還順便分享使用心得。更棒的是,搭配蝦皮分潤計畫,愛用品不僅自己用得安心,分享給朋友還能賺回饋。立即使用推薦碼 X5Q344E,輕鬆上手,隨時隨地賺取分潤!
Thumbnail
不知你有沒有過這種經驗?衛生紙只剩最後一包、洗衣精倒不出來,或電池突然沒電。這次一次補貨,從電池、衛生紙到洗衣精,還順便分享使用心得。更棒的是,搭配蝦皮分潤計畫,愛用品不僅自己用得安心,分享給朋友還能賺回饋。立即使用推薦碼 X5Q344E,輕鬆上手,隨時隨地賺取分潤!
Thumbnail
身為一個典型的社畜,上班時間被會議、進度、KPI 塞得滿滿,下班後只想要找一個能夠安靜喘口氣的小角落。對我來說,畫畫就是那個屬於自己的小樹洞。無論是胡亂塗鴉,還是慢慢描繪喜歡的插畫人物,那個專注在筆觸和色彩的過程,就像在幫心靈按摩一樣,讓緊繃的神經慢慢鬆開。
Thumbnail
身為一個典型的社畜,上班時間被會議、進度、KPI 塞得滿滿,下班後只想要找一個能夠安靜喘口氣的小角落。對我來說,畫畫就是那個屬於自己的小樹洞。無論是胡亂塗鴉,還是慢慢描繪喜歡的插畫人物,那個專注在筆觸和色彩的過程,就像在幫心靈按摩一樣,讓緊繃的神經慢慢鬆開。
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
只要在軟體公司待過,一定對於敏捷式開發不陌生,在現在的年代,是一種頗為主流的開發方式,這種開發方式,有著開發期短、彈性大、持續迭代的特性,但有時候不免會帶來一些技術債、版本管理的問題。 反正只要有了問題,只要快速的修正、並且上新版本去調整即可。 "難道不可以同時進行嗎?" 這樣,真的有比較快嗎?
追蹤感興趣的內容從 Google News 追蹤更多 vocus 的最新精選內容追蹤 Google News