iT邦幫忙

2021 iThome 鐵人賽

DAY 11
0
Modern Web

以 React 為主的那些前端事系列 第 11

Day 11 - 那個很常用到的 useEffect

  • 分享至 

  • xImage
  •  

如果有錯誤,歡迎留言指教~ Q_Q

先說說什麼是 side effect ?

就是不在主要的程式執行順序上~~ 在瀏覽器 render 之後才會執行

像是更新取得資料或操作畫面上的 Dom 做些動態效果

而寫的這些事情 function 我們將其稱為「effect」

在 component render (DOM 更新之後),才會執行的這些 effect

useEffect: component 在 render 之後做的事情 (side effect)

如果你比較熟悉生命週期,那可以把 useEffect 當作 componentDidMountcomponentDidUpdate,與 componentWillUnmount 的組合

但把 effect 想成發生在「render 之後」比較簡單,而不要考慮這時是「mount」還是「update」

在 class component 裡,無論是 mount 或是 update,你需要在兩個地方維護同一份程式碼,雖然你可以寫個共用的 function ,但你還是必須在兩個地方 call function

  // 換一下範例好了
  componentDidMount() {
    document.title = `You clicked ${this.state.count} times`;
  }
  componentDidUpdate() {
    document.title = `You clicked ${this.state.count} times`;
  }

useEffect 就可以寫一次就好了~
function 就會在 render 後執行

  // 換一下範例好了
  useEffect(() => {
    document.title = `You clicked ${count} times`;
  });

在 useEffect 裡 return function -> 清除

在生命週期裡,會在 componentDidMount 中設定好初始要做的事情
然後在 componentWillUnmount 中把它清除釋放掉

那在 Hook 裡面,我們該怎麼做呢?

我們在 useEffect 中 return 執行清除的 function

這使我們可以把 Mount、Update、Unmount 的邏輯都放在一起了~

因為它們都屬於同一個 effect!

useEffect(() => {
let update;

if (updateTab) {
  update = setInterval(() => {
    cronFetch(updateTab);
  }, UPDATE_TIME);
}

// 釋放掉吧!事件移除、取消綁定
return () => clearInterval(update);
}, []);

有什麼情況會讓 useEffect 知道何時該執行呢?

元件因為狀態(state/props)改變了,觸發 useEffect 產生了什麼效果

  1. 第一次 render component
  2. 當 state 更新後的 render
useEffect(()=>{
    // 做 data 變化後,要做的事情
    // 綁定事件
    alert('新增成功')

    // 事件移除
    return () => {
        // 取消綁定 removeEventListener
    } 
},[data]);
// 當依賴的 state 的 data 有變動,useEffect 就會執行
    

useEffect 的 dependencies: 一組 array []

useEffect 帶著兩組參數

第一個是執行的 function

第二個則是該 effect 所依賴的值 array -> 決定要偵測誰才觸發 effect

當遇到什麼事情,這個 array list 有變化時(也可能是空值),就會去執行上面的 function

  1. 當 [] 沒有任何值: 只有第一次會執行,因為沒有值可以參考變化了 → 模擬 didmouont
useEffect(()=>{
    console.log('只有第一次 render 會執行')
},[]);
  1. 當 [] 帶些參考值: 當參考的值改變了就會執行,包含第一次 render

https://codesandbox.io/s/useeffect-r35sw

import { useState, useEffect } from "react";

export default function App() {
  const [data, setData] = useState("");
  const [value, setValue] = useState("!");

  useEffect(() => {
    console.log(data);
  }, [data]);

  return (
    <div className="App">
      <button
        onClick={() => {
          console.log("click");
          setData(new Date());
        }}
      >
        click
      </button>
    </div>
  );
}

  1. 當沒有 [] : 每次 render 都會執行,包含第一次 render
useEffect(()=>{
    console.log('每次 render 都會執行')
});

useEffect 的 dependencies 注意事項

  1. dependencies[] 裡面,要放 useEffect function 有用到的值: props 或 state
  2. dependencies[] 的值,不要是會在 useEffect 裡面改動他,不然容易會無限迴圈
  3. 建議 dependencies 不要放 object{}、list[],而是用 primative type: number、boolean、string

可以有很多 useState,也可以有很多的 useEffect

如果 dependencies array 彼此之間沒有相關的話,就拆分不同的 useEffect 吧

要多少 Effect 就多少 Effect ~~~

把邏輯相同的放在一起即可!

ref:

  1. https://zh-hant.reactjs.org/docs/hooks-effect.html

上一篇
Day 10 - 非同步的 setState()
下一篇
Day 12 - 那個被我忘記的 ref / useRef / createRef 上
系列文
以 React 為主的那些前端事30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言