昨天我們介紹了 useEffect 的觸發時機,根據 useEffect 第二個參數 [dependency]
的不同會有不同的觸發時機,今天我們就來看看 useEffect 實際可以運用在哪種情形
想像一下我們在瀏覽網頁的時候,像是 youtube 的時候,一進入首頁的會給你許多推薦的影片,但這時發現這些影片中,沒有我喜歡的影片,那我們可能會去選擇搜尋關鍵字,或是點擊旁邊的 silebar 去選擇我們喜歡的種類,這網站就會依照我們的要求去獲得不同的資料,最後顯示在畫面,那這跟 useEffect 有關係嗎 ? 還記得 useEffect的觸發時機嗎,初次渲然會觸發執行,再來就要看 第二個參數 [dependency]
給予的條件了,他就很像監聽器會監聽這個 array 的數值有沒有變動
讓我們使用這個網站為例 (https://jsonplaceholder.typicode.com/)
import React, { useState, useEffect } from "react";
import Axios from "axios";
import "./fetchData.css";
const FetchData = () => {
const [list, setList] = useState([]);
useEffect(() => {
Axios({ url: `https://jsonplaceholder.typicode.com/users` })
.then(response => {
setList(response.data);
})
.catch(error => {
console.log(error);
});
}, []);
return (
<div className="listStyle">
<div className="listContainer">
{list.map(item => (
<div className="listItem" key={item.id}>
<h3>{item.id}</h3>
<h3>標題:{item.name}</h3>
</div>
))}
</div>
</div>
);
}
export default FetchData;
這樣在我的 React 初次 render 畫面的時候,就會執行 useEffect,並且只會執行一次
那你會認為說我可以不要用 useEffect,我直接讓 function 去打 API 就好了,反正我只要 setList(response.data)
成功之後。
我的 list
就不會改變了啊,這樣也不會執行過多的渲染,
但是夢想總是美好的~
讓我們看看這樣做會發生什麼事,我們將 useEffect 拔掉變成這樣
Axios({ url: `https://jsonplaceholder.typicode.com/users` })
.then(response => {
setList(response.data);
console.log("成功獲得資料");
})
.catch(error => {
console.error(error);
});
會發現出大事了!怎麼出現無窮迴圈了
那就讓我來用這個例子來說明,我們就會清楚發生什麼事了!
因為 React useState 中,我們使用 setState 會比較 oldvalue 跟 newvalue 用(===)比較,也就是說比較 舊值 跟 新值 若兩個有不同就重新執行這個 Component, 但是用從上圖可以看到 a 跟 b ,兩個不是一樣嗎?
你只能說他們看起來一樣~
在 JavaScript 的世界中,字串、數字、布林值,都是 Call by value
但是 陣列,物件,function 都是 Call by reference
,也就是會去比較他們記憶體位址的不同,所以雖然看起來是一樣的,實際上記憶體位址是不同的,所以若沒有用 useEffect 去執行,fetch API 的話每次 setList
時其實都是不同的,因為在 array陣列中 React 會去比較 reference 的是否有不同,所以若是每次都不同的話,就會重新渲染畫面,
所以才會造成無限迴圈,所以就讓我們乖乖地使用 useEffect 吧!
今天說明了我們在打 API 時為什麼要使用 useEffect,他的目的為何,又能幫我們解決什麼事,明天將會接續下去我們該如何在同一個頁面會去不同資料