iT邦幫忙

第 12 屆 iThome 鐵人賽

DAY 19
0
自我挑戰組

菜雞們,讓我們一起征服JS及React吧系列 第 19

React菜雞-Day19:React第四招 - useEffect 讓你掌握Component的生命週期

  • 分享至 

  • xImage
  •  
tags: 鐵人賽 React javascript nodejs

鐵人賽第19天,我們來好好了解一下useEffect,同時,我們也會學習React的生命週期
/images/emoticon/emoticon12.gif

關於React的生命週期

  • React定義了component的生命週期,提供開發者能夠精準的設置相對應的動作。
  • Render做一個時間軸的分隔線,後面的代表component已繪製於畫面中,其中:
  • ComponentDidMount: 元件已經完成繪製
  • *ComponentDidUpdate: state已經更新完成
  • ComponrntWillUnMount: 元件即將移除畫面

useEffect的第一個變數

ComponentDidMount

  • 我們建立一個新的componrnt,建立檔案EffectApp.js,同時將index.js引入使用。
  • EffectApp組件組成有:
  • 一個div顯示title
  • 一個button,有toggle的功能,實現state的切換,決定title是否顯示
//EffectApp.js
import React, { useState, useEffect } from "react";  //<-- import引入 useEffect

export default function EffectApp() {
  const [state, setState] = useState(true);

  // 建立一個useEffect
  useEffect(() => {
    console.log("ComponentDidMount...");
  });

  let handleClick = (setState) => {
    return (e) => {
      setState(!state);
    };
  };

  return (
    <>
      <button onClick={handleClick(setState)}>{state?"delete":"show"}</button>
      <div>{state&& "Learn useEffect"}</div>
    </>
  );
}

  • 剛開始啟動時,你會發現,ComponentDidMount...已經顯示於console window中,代表所有的component已經顯示於畫面之上囉!

ComponentDidUpdate

//EffectApp.js
import React, { useState, useEffect } from "react";

export default function EffectApp() {
  const [state, setState] = useState(true);

  useEffect(() => {
    console.log("ComponentDidMount...");

    return () => console.log("ComponentDidUpdate!!!");  //<-- 在這裡回傳一個func,當狀態改變時,React會自動呼叫這個函式執行
  });

  let handleClick = (setState) => {
    return (e) => {
      setState(!state);
    };
  };

  return (
    <>
      <button onClick={handleClick(setState)}>{state?"delete":"show"}</button>
      <div>{state&& "Learn useEffect"}</div>
    </>
  );
}

  • 有沒有注意到,當 (1)狀態改變,(2)元件消失或出現時console window會依序印出
  1. 狀態改變 => 呼叫回傳的funcreturn () => console.log("ComponentDidUpdate!!!");
  2. 元件消失或出現 => 呼叫 console.log("ComponentDidMount...");

useEffect的第二個變數

  • 第二個參數是一個Array,提供給React決定要呼叫的
//EffectApp.js
import React, { useState, useEffect } from "react";

export default function EffectApp() {
  const [state1, setState1] = useState(true);
  const [state2, setState2] = useState(true);

  // for state1
  useEffect(() => {
    console.log("*** area1 ***");
    console.log("[state1]: ComponentDidMount...");
    return () => console.log("[state1]: ComponentDidUpdate!!!");  
  }, [state1]);

  // for state2
  useEffect(() => {
    console.log("=== area2 ===");
    console.log("[state2]: ComponentDidMount...");
    return () => console.log("[state2]: ComponentDidUpdate!!!");  
  },[state2]);

  let handleClick = (setState, aState) => {
    return (e) => {
      setState(!aState);
    };
  };

  return (
    <>
      <button onClick={handleClick(setState1, state1)}>{state1?"delete1":"show1"}</button>
      <div>{state1&& "area1"}</div>

       <br/>
      <button onClick={handleClick(setState2, state2)}>{state1?"delete2":"show2"}</button>
      <div>{state2&& "area2"}</div>
    </>
  );
}

先來看看初始畫面

  • 各自ComponentDidMount都有被呼叫,符合期待

按下 area1的按鈕

  • 從畫面藍色的框框開始,你會發現,ComponentDidUpdate先被觸發,因為state1確實被更新了!
  • 接著,area1title消失,因此呼叫ComponentDidMount,符合預期!

接著,按下area2的按鈕

  • 從藍色的框框開始,和按下area1的按鈕一樣,也符合我們對state2的預期

那...如果給空的array呢?

  • 我們將第二個useEffect的第二個變數,給予空的Array,來看看會有什麼有趣的事
//EffectApp.js
...
  // for state2
  useEffect(() => {
    console.log("=== area2 ===");
    console.log("[state2]: ComponentDidMount...");
    return () => console.log("[state2]: ComponentDidUpdate!!!");  
  },[]); //<-- 給空的陣列,看看會有什麼有趣的事

...

/images/emoticon/emoticon33.gif

  • 有沒有注意到,area2ComponentDidMount在畫面一開始顯示時有被呼叫,之後,不管我怎麼按area2的按鈕,他都不會有任何反應,
  • 這是因為React會依據第二個參數的Array內容,來決定是否觸發ComponentDidMountComponentDidUpdate
  • 因此,useEffect第二個參數給予空的陣列,僅會執行一次!

你不是說還有ComponentWillUnMount

  • 其實,在React Hook中,ComponentWillUnMountComponentDidUpdate都會跟著呼叫你回傳的函示。
  • 因此,我們可以整理如下的使用方式
useEffect(()=>{
    // component did Mount
    
    return ()=>{
    // component did update 
    // componrnt will unMount
    }
}, [
    // 空陣列代表僅執行一次, 
    // 放入state或component,代表只要他們有變動,就會觸發呼叫useEffect
    //])

結論

  • 今天,我們初步的了解useEffectReact lifecycle之間的關係,useEffect有很多進階的應用,我們會在未來好好的跟各位詳談,請期待!
  • 鐵人賽第19天,又是一個忙到忘我的一天,好在撐過來了,繼續加油~Rock~~~ /images/emoticon/emoticon62.gif

上一篇
React菜雞-Day18:實戰!寫個To Do List - part3 優化使用者體驗
下一篇
React菜雞-Day20:學會JS獨特的用法,讓你的React更優雅~箭頭函示
系列文
菜雞們,讓我們一起征服JS及React吧30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言