iT邦幫忙

2021 iThome 鐵人賽

DAY 23
0
自我挑戰組

登堂入室!前端工程師的觀念技術 _30_ 題系列 第 23

22. React Hooks --- useEffect

用途


  • useEffect能夠指定元件(component)渲染(render)完畢後,執行function。
  • React 會記住被傳入useEffect的function(= effect),並在執行 DOM 更新之後呼叫function。
  • 可以用來請求資料或呼叫API。
    (資料 fetch、手動改變DOM元素,這些動作都被稱作side effect。)

語法


useEffect(function[,array]);

useEffect可以放入兩個參數:

  • function
    第一個是每次render要執行的function。
  • [,array]
    第二個是陣列。這是選擇性的參數。(不放也沒關係,預設就是每次畫面更新時觸發。)
    React會在陣列裡的值有變動時,觸發第一個參數的function。

示例


React官方提供了這樣的例子進行示範:

const { useState, useEffect } = React

const App = () => {
  
  const [count, setCount] = useState(0);

  useEffect(() => {
    console.log(`You clicked ${count} times`);
  });

  return (
    <div>
        <p>You clicked {count} times</p>
        <button onClick={() => setCount(count + 1)}>
          Click me
        </button>
    </div>
  )
}

ReactDOM.render(<App />,
document.getElementById("root"))

執行結果:
https://ithelp.ithome.com.tw/upload/images/20210923/20129476yKPEHgzzVx.png

可以看到在初次畫面渲染時,console就已經顯示"You clicked 0 times"。隨後,每次點擊時,就會隨著state被更新的次數(畫面重新渲染)時執行。(類似lifecycle的componentDidMount,
可以參閱這篇文章:【Day 9】Component Lifecycle - iT 邦幫忙)

→ 在component內部呼叫useEffect,這樣能夠直接調用component內部的state或props。
useEffect會在每次render後執行,包含第一次render和每次更新useEffect


useEffect可以指定一個回傳(return)函式

如果你的 effect 回傳了一個 function,React 將在需要清除時執行它。

回傳函式的用途是一種清除機制,清除不需要的effect是為了防止memory leak :
由於錯誤,造成程式未能釋放已經不再使用的記憶體,導致在釋放該段記憶體之前就失去了對該段記憶體的控制,造成記憶體的浪費。

改變一下上面的例子:

const { useState, useEffect } = React

const App = () => {
  
  const [count, setCount] = useState(0);

  useEffect(() => {
    console.log(`You clicked ${count} times`);
    return () => {
      console.log(`return: You clicked ${count} times`);
    }
  });
  
  return (
    <div>
        <p>You clicked {count} times</p>
        <button onClick={() => setCount(count + 1)}>
          Click me
        </button>
    </div>
  )
}

ReactDOM.render(<App />,
document.getElementById("root"))

執行結果:
https://ithelp.ithome.com.tw/upload/images/20210923/2012947623UeBOlJeA.png

這是點擊了按鈕兩次的範例,可以看到輸出的順序:

"You clicked 0 times"          // 初次渲染時執行

"return: You clicked 0 times"  // 第一次 點擊按鈕後,state更新 前。
"You clicked 1 times"          // 第一次 點擊按鈕後,state更新 後。

"return: You clicked 1 times"  // 第二次 點擊按鈕後,state更新 前。
"You clicked 2 times"          // 第二次 點擊按鈕後,state更新 後。

所以這裡可以知道,
→ return的function會在元件更新前執行。(類似componentWillUnmount)


useEffect的第二個參數

React會在第二個參數[陣列]裡的值有變動時,觸發第一個參數的function。

上面的範例都沒有應用到useEffect的第二個參數,所以現在來嘗試使用他:

const { useState, useEffect } = React

const App = () => {
  
  const [count, setCount] = useState(0);

  useEffect(() => {
    console.log(`1st useEffect: You clicked ${count} times`);
  },[]);     //傳入空陣列
  
  useEffect(() => {
    console.log(`2nd useEffect:You clicked ${count} times`);
  },[count]);      //傳入參數
  
  return (
    <div>
        <p>You clicked {count} times</p>
        <button onClick={() => setCount(count + 1)}>
          Click me
        </button>
    </div>
  )
}

ReactDOM.render(<App />,
document.getElementById("root"))

執行結果:
https://ithelp.ithome.com.tw/upload/images/20210923/20129476GZeWuJhYen.png

這裡可以整理簡單的結論:

  1. 被放入空陣列的useEffect,因為沒有需要觀察的參數,所以只在第一次渲染時執行。
  2. 放入statecount的useEffect,會在每次state被更動時執行。

提問

  1. useEffect 回傳的 function 用途是什麼?
    在 React 下一次執行 effect 前,清除前一個 render 的 effect。(可以防止記憶體流失。)

  2. useEffect 傳入的第二個參數作用是什麼?
    傳入需要被觀察的變數,可以控制使用useEffect的時機。

【如內文有誤還請不吝指教>< 並感謝閱覽至此的各位:D 】

參考資料
-使用 Effect Hook
(↑官方文件有解釋為什麼 Effect 會在每次更新時執行,有興趣可以參考看看。)
-【Day 10】第二個 hook - useEffect - iT 邦幫忙::一起幫忙解決難題,拯救 IT 人的一天

---正文結束---


上一篇
21. React簡易實作_購物車清單( 將下層State提升給上層元件 )
下一篇
23. React key 的用途
系列文
登堂入室!前端工程師的觀念技術 _30_ 題31

尚未有邦友留言

立即登入留言