React如何處理非同步的資料-useEffect的使用方法與設計影響

更新於 發佈於 閱讀時間約 5 分鐘



當前大多數網站不再是靜態網站,需要向後端的 Server 請求資料。而且,這些資料的請求通常是非同步進行的。在React中,目前被視為最佳實踐的方式是使用 useEffect。

用useEffect的起手式


export default function Component(){
//1.先設置狀態用來儲存從後端獲取的資料
const [data,setData] = useState(null);
useEffect(
() => {
const fetchData = async () => {
const newData = await getDataApi();
setData(newData);
};
fetchData();
},[]);
//2.由於 useEffect 中沒有會觸發的變數,所以 dependency 為 []
return
<>
<p>畫面中其他的東西</p>
{data}
</>
}

useEffect 是甚麼

在解析上面的程式碼在做什麼之前,我們先來了解甚麼是 useEffect。

useEffect 的參數接收一個function,這個 function 就是副作用,會在每一次 Render 之後執行的。

Render 也就是執行 component 這個 function,useEffect 中的 function (副作用) 會在 function Component 的其他程式碼都執行之後才執行。

運作的方式與順序

接著,我們就來看上面的起手式是如何運作吧。

  1. 第一次執行 App 的 function(第一次 Render)
    1. 用useState設置 state 變數- data (目前是 null)
    2. return 包含 data 的 HTML (其實是 React Element)
    3. 最後執行 useEffect中的 function ,發送 API 取得 newData ,並用以更新 data (變成newData)
    4. 因為 執行了 setData,且 data 的值有改變,所以觸發第二次 Render
  2. 第二次執行App 的 function (第二次 Render)
    1. App 函數再次被呼叫,但此時 data 的值已經是由 API 取得的新數據 newData
    2. 返回的 JSX 元素中的 data 將呈現最新的資料
    3. 沒有 state 變化會在觸發 render與 useEffect ,所以程式中止

由此可見,使用 useEffect 來對 API 取得資料會有兩個特點

1.這個元件會執行(Render)兩次

2.在第一次的 data 為預設值(null),在第二次才是從api取得的資料

為什麼要這麼做?

我一開始使用 useEffect 來取得 API 的資料,感到納悶為甚麼要用這個方式。為甚麼不要一次就把事情做完( Render 一次),要做兩次( Render 兩次)呢?

這樣分兩次做的好處是讓使用者有更好的體驗。在第一次的 render 中,畫面中的其他元素會先被渲染出來,之後在第二次 render 的時候,再把從 api 中取得的資料渲染出來。因為從 API 取得資料需要較長的時間,在第一次 render 時先把主要畫面的元素呈現給使用者看,讓使用者有東西可以先看,使用者比較不會感受到等待取得 API 資料的漫長的時間(如果她的網路很慢的話)。

這就像是我今天跟你借了100萬,我用兩種方式還你錢。

1.我每 3 個月還你 20 萬

2.我一年後一次還你 100 萬

雖然第一種方式我總共用了 15 個月才還完 100 萬,但是你一定覺得第一種方式比第二種方式舒服跟安心多了,你不會在這一年一直擔心我會不會還錢。

因應第一次 Render 沒資料的設計

在閱讀至此,您可能已經留意到一個重要的問題:

data 只有在 useEffect 中獲取資料後,才會在第二次渲染時擁有實際的數據。

那麼我針對data的處理不就會出錯?

是的,所以在處裡 data 時,要先考慮到 data 沒資料的情況。

解決這個問題的方式有兩種:

  1. 使用條件判斷避免錯誤: 在處理 data 的程式碼之前,可以加上以下其中之一的條件判斷:
    // 使用 "data &&" 避免在 data 為 null 或 undefined 時執行相關程式碼
    if (data) {
    data.map(...);
    // 或其他處理 data 的程式碼
    }
    或者
    // 使用 "if (data)" 確認 data 不為 null 或 undefined 才執行相關程式碼
    if (data) {
    data.user...;
    // 或其他處理 data 相關的程式碼
    }
    這樣可以確保相關處理只在 data 有資料時執行,從而避免在第一次渲染時出現錯誤。
  2. 搭配 loading 元件: 另一種方法是搭配 loading 元件,在第一次渲染時返回這個 loading 元件:
    // 使用 useState 時,將 data 的初始值設為 null
    if (data === null) {
    return <Loading />;
    }
    // 此處繼續渲染包含實際資料的 JSX 元素


總結

透過使用 useEffect 來獲取 API 資料,我們可以確保這項相對耗時的非同步操作在第一次渲染後才執行,避免讓使用者在等待 API 資料取得的同時看著空畫面。

同時,我們也必須注意到在第一次渲染時,data 還沒有實際資料,因此在處理資料時需要先考慮這個狀態。

留言
avatar-img
留言分享你的想法!
avatar-img
Shang的 前端開發筆記
3會員
13內容數
歡迎來到我的部落格!這裡是一個分享前端開發、貓咪寫真以及與菲律賓女友生活的文化衝擊與英文學習的個人空間。我熱愛前端技術,喜歡追求最新的網頁開發趨勢,並將這些知識分享給大家。
2024/03/21
CatHelper是我開發的前端 SideProject,是貓咪募資收養的一站式平台。 我用戶使用流程、資料庫、頁面來構思這個專案。
Thumbnail
2024/03/21
CatHelper是我開發的前端 SideProject,是貓咪募資收養的一站式平台。 我用戶使用流程、資料庫、頁面來構思這個專案。
Thumbnail
2024/03/14
不同的運算子一起出現時,會根據其優先性(Precedence)來決定誰先誰後。MDN也很貼心的整理成表格了。 雖然有表格可以供我們查找,但是總不可能每一次用到運算子的時候,我們都去查找吧?我們最好對這張表有直觀上的理解與記憶。 那麼就讓我來分享我如何理解與記憶這張表吧! 運算子在做甚麼
Thumbnail
2024/03/14
不同的運算子一起出現時,會根據其優先性(Precedence)來決定誰先誰後。MDN也很貼心的整理成表格了。 雖然有表格可以供我們查找,但是總不可能每一次用到運算子的時候,我們都去查找吧?我們最好對這張表有直觀上的理解與記憶。 那麼就讓我來分享我如何理解與記憶這張表吧! 運算子在做甚麼
Thumbnail
2023/10/20
我在學習vue的過程中,一開始是先從輕前端(用CDN引入)開始學。這時候看Vue的官方文件會有些困惑,原因是有沒有用vite建構,在元件寫法上會有些差異。所以我寫下這篇筆記來整理這兩者寫法上的差異。 起手式 1.非建構:使用cdn 在html的header中插入以下script標籤 <s
2023/10/20
我在學習vue的過程中,一開始是先從輕前端(用CDN引入)開始學。這時候看Vue的官方文件會有些困惑,原因是有沒有用vite建構,在元件寫法上會有些差異。所以我寫下這篇筆記來整理這兩者寫法上的差異。 起手式 1.非建構:使用cdn 在html的header中插入以下script標籤 <s
看更多
你可能也想看
Thumbnail
透過蝦皮分潤計畫,輕鬆賺取零用金!本文分享5-6月實測心得,包含數據流程、實際收入、平臺優點及注意事項,並推薦高分潤商品,教你如何運用空閒時間創造被動收入。
Thumbnail
透過蝦皮分潤計畫,輕鬆賺取零用金!本文分享5-6月實測心得,包含數據流程、實際收入、平臺優點及注意事項,並推薦高分潤商品,教你如何運用空閒時間創造被動收入。
Thumbnail
單身的人有些會養寵物,而我養植物。畢竟寵物離世會傷心,植物沒養好再接再厲就好了~(笑)
Thumbnail
單身的人有些會養寵物,而我養植物。畢竟寵物離世會傷心,植物沒養好再接再厲就好了~(笑)
Thumbnail
不知你有沒有過這種經驗?衛生紙只剩最後一包、洗衣精倒不出來,或電池突然沒電。這次一次補貨,從電池、衛生紙到洗衣精,還順便分享使用心得。更棒的是,搭配蝦皮分潤計畫,愛用品不僅自己用得安心,分享給朋友還能賺回饋。立即使用推薦碼 X5Q344E,輕鬆上手,隨時隨地賺取分潤!
Thumbnail
不知你有沒有過這種經驗?衛生紙只剩最後一包、洗衣精倒不出來,或電池突然沒電。這次一次補貨,從電池、衛生紙到洗衣精,還順便分享使用心得。更棒的是,搭配蝦皮分潤計畫,愛用品不僅自己用得安心,分享給朋友還能賺回饋。立即使用推薦碼 X5Q344E,輕鬆上手,隨時隨地賺取分潤!
Thumbnail
身為一個典型的社畜,上班時間被會議、進度、KPI 塞得滿滿,下班後只想要找一個能夠安靜喘口氣的小角落。對我來說,畫畫就是那個屬於自己的小樹洞。無論是胡亂塗鴉,還是慢慢描繪喜歡的插畫人物,那個專注在筆觸和色彩的過程,就像在幫心靈按摩一樣,讓緊繃的神經慢慢鬆開。
Thumbnail
身為一個典型的社畜,上班時間被會議、進度、KPI 塞得滿滿,下班後只想要找一個能夠安靜喘口氣的小角落。對我來說,畫畫就是那個屬於自己的小樹洞。無論是胡亂塗鴉,還是慢慢描繪喜歡的插畫人物,那個專注在筆觸和色彩的過程,就像在幫心靈按摩一樣,讓緊繃的神經慢慢鬆開。
Thumbnail
在網路速度有限的情況下,依序記錄不斷產生的資訊,能統計使用者在頁面上操作了哪些功能。
Thumbnail
在網路速度有限的情況下,依序記錄不斷產生的資訊,能統計使用者在頁面上操作了哪些功能。
Thumbnail
※ 靜態資源回傳 ※ 什麼是靜態資源: 定義:是指事先準備好的資源,這些資源在伺服器上是靜態的、不會隨著每個請求而改變。 資源通常包括: 靜態 HTML 文件。 CSS。 圖像(Image)。 Video。 字體文件:google fonts。 favicon:網頁名稱旁邊的ico
Thumbnail
※ 靜態資源回傳 ※ 什麼是靜態資源: 定義:是指事先準備好的資源,這些資源在伺服器上是靜態的、不會隨著每個請求而改變。 資源通常包括: 靜態 HTML 文件。 CSS。 圖像(Image)。 Video。 字體文件:google fonts。 favicon:網頁名稱旁邊的ico
Thumbnail
到底要用 ref 還是 reactive 是一個很常見的問題,不過現在官方文檔推薦使用 ref 就行,所以也不是甚麼大問題就是了。( •̀ ω •́ )✧ 所以 reactive 真的沒用用途了嗎?這篇文章來記錄一下 reactive 的用法。
Thumbnail
到底要用 ref 還是 reactive 是一個很常見的問題,不過現在官方文檔推薦使用 ref 就行,所以也不是甚麼大問題就是了。( •̀ ω •́ )✧ 所以 reactive 真的沒用用途了嗎?這篇文章來記錄一下 reactive 的用法。
Thumbnail
在程式任何地方都能修改各種react組件狀態的做法分享
Thumbnail
在程式任何地方都能修改各種react組件狀態的做法分享
追蹤感興趣的內容從 Google News 追蹤更多 vocus 的最新精選內容追蹤 Google News