iT邦幫忙

2023 iThome 鐵人賽

DAY 15
0
自我挑戰組

React 個人讀書會系列 第 15

Day 15 - 執行副作用:useEffect

  • 分享至 

  • xImage
  •  

https://ithelp.ithome.com.tw/upload/images/20231009/20103817zn6cHsZ2lc.jpg

為什麼需要 useEffect?

以下是一個範例,我們一開始透過 fetch 方法從遠端 API 取得資料,並將取的回來的資料 data.Search 透過 set 函式更新到 movies 狀態,在這個過程中會發生什麼事情呢?

function App() {
  const [movies, setMovies] = useState([]);
  const [query, setQuery] = useState("");

  fetch(`https://www.omdbapi.com/s={query}`)
    .then((res) => res.json())
    .then((data) => setMovies(data.Search));
}
  1. movies 狀態更新時,元件會 重新渲染 並再次執行函式元件。
  2. 此時,fetch 行為會再次被觸發,進而再次更新 movies 狀態。

是否已經察覺到問題了呢?這個元件會不斷重複 1 跟 2 的行為,導致無窮迴圈,因此,在這個地方直接執行 fetch 操作是不可行的。

使用 useEffect 處理副作用

useEffect 是 React 提供的一個 Hook,它用於處理元件中的副作用(Side Effect)操作,例如取得 API 資料、DOM 操作等。

function App() {
  const [movies, setMovies] = useState([]);
  const [query, setQuery] = useState("");

  useEffect(() => {
    fetch(`https://www.omdbapi.com/s={query}`)
	  .then((res) => res.json())
	  .then((data) => setMovies(data.Search));
  })
}

這邊要特別注意,雖然我們已經將 API 操作放入 useEffect 內,但我們還缺少了一個非常重要的參數:依賴陣列。

useEffect 的依賴陣列

  1. 如果沒有依賴陣列,React 不知道什麼時候運行 effect。
function User({ userId }) {
  const [user, setUser] = useState({});
  const [query, setQuery] = useState("");

  // 沒有傳遞依賴陣列,每次重新渲染都會執行這段 effect
  useEffect(() => {
    fetch(`https://www.omdbapi.com/s={query}`)
	  .then((res) => res.json())
	  .then((data) => setMovies(data.Search));
  })
}

  1. 默認情況下,effect 在每次渲染後運行,我們可以通過傳遞依賴陣列來防止這種情況。
function App() {
  const [movies, setMovies] = useState([]);
  const [query, setQuery] = useState("");

  // 傳遞一個依賴陣列,空陣列代表只有在初始渲染的時候執行一次
  useEffect(() => {
    fetch(`https://www.omdbapi.com/s={query}`)
	  .then((res) => res.json())
	  .then((data) => setMovies(data.Search));
  }, [])
}
  1. 每當依賴陣列中的任何一個參數發生變化,effect 就會再次運行。
function App() {
  const [movies, setMovies] = useState([]);
  const [query, setQuery] = useState("");

  // 初始渲染的時候執行一次
  // 當 query 發生變化時,將重新執行這段 effect
  useEffect(() => {
    fetch(`https://www.omdbapi.com/s={query}`)
	  .then((res) => res.json())
	  .then((data) => setMovies(data.Search));
  }, [query])
}
  1. Effect 使用的每個狀態和屬性必須包含在依賴陣列中,否則 React 無法知道此更改,因此它將無法重新執行 effect。
function App() {
  const [movies, setMovies] = useState([]);
  const [query, setQuery] = useState("");

  // 初始渲染的時候執行一次
  // 當 query 發生變化時,將重新執行這段 effect
  useEffect(() => {
    fetch(`https://www.omdbapi.com/s={query}`)
	  .then((res) => res.json())
	  .then((data) => setMovies(data.Search));
  }, [query])
}

結語

透過 useEffect,我們能夠有效處理元件中的副作用操作,並通過適當設定依賴陣列,掌握何時運行這些操作,同時避免不必要的重新渲染。


上一篇
Day 14 - 屬性的深層傳遞:Prop Drilling
下一篇
Day 16 - useEffect 的好麻吉:Cleanup Function
系列文
React 個人讀書會30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言