鐵人賽 React javascript nodejs
鐵人賽第19天,我們來好好了解一下useEffect,同時,我們也會學習React的生命週期!![]()
React定義了component的生命週期,提供開發者能夠精準的設置相對應的動作。
Render做一個時間軸的分隔線,後面的代表component已繪製於畫面中,其中:
- ComponentDidMount: 元件已經完成繪製
 - *ComponentDidUpdate: state已經更新完成
 - ComponrntWillUnMount: 元件即將移除畫面
 
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已經顯示於畫面之上囉!//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>
    </>
  );
}

console window會依序印出
- 狀態改變 => 呼叫回傳的func
 return () => console.log("ComponentDidUpdate!!!");- 元件消失或出現 => 呼叫
 console.log("ComponentDidMount...");
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都有被呼叫,符合期待
ComponentDidUpdate先被觸發,因為state1確實被更新了!area1的title消失,因此呼叫ComponentDidMount,符合預期!
area1的按鈕一樣,也符合我們對state2的預期
useEffect的第二個變數,給予空的Array,來看看會有什麼有趣的事//EffectApp.js
...
  // for state2
  useEffect(() => {
    console.log("=== area2 ===");
    console.log("[state2]: ComponentDidMount...");
    return () => console.log("[state2]: ComponentDidUpdate!!!");  
  },[]); //<-- 給空的陣列,看看會有什麼有趣的事
...

![]()
area2的ComponentDidMount在畫面一開始顯示時有被呼叫,之後,不管我怎麼按area2的按鈕,他都不會有任何反應,React會依據第二個參數的Array內容,來決定是否觸發ComponentDidMount及ComponentDidUpdate
useEffect第二個參數給予空的陣列,僅會執行一次!React Hook中,ComponentWillUnMount及ComponentDidUpdate都會跟著呼叫你回傳的函示。useEffect(()=>{
    // component did Mount
    
    return ()=>{
    // component did update 
    // componrnt will unMount
    }
}, [
    // 空陣列代表僅執行一次, 
    // 放入state或component,代表只要他們有變動,就會觸發呼叫useEffect
    //])
useEffect及React lifecycle之間的關係,useEffect有很多進階的應用,我們會在未來好好的跟各位詳談,請期待!