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 還沒有實際資料,因此在處理資料時需要先考慮這個狀態。

    歡迎來到我的部落格!這裡是一個分享前端開發、貓咪寫真以及與菲律賓女友生活的文化衝擊與英文學習的個人空間。我熱愛前端技術,喜歡追求最新的網頁開發趨勢,並將這些知識分享給大家。
    留言0
    查看全部
    發表第一個留言支持創作者!