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 人的一天

---正文结束---


<<:  【Day 8】节点间的共识(Consensus)

>>:  [Day 8]开赛八天即遭遇难题(前端篇)

[Day_4]Python 字串(1)

字串 在Python里扮演很重要的角色, 使用**单引号「'」与双引号「"」**所包含的文...

Day 14 | Flutter 基本介绍

什麽是Flutter 正如第一篇文章所说的 Flutter 是一个「框架」,可以用来开发跨平台原生的...

[Day06] 用 .NET 实做简单的 RESTful API

HTTP request 上次我们建立了一个直接能跑的专案,但是它只有一个回传随机天气的 API 接...

你的 MVVM 不是你的 MVVM

相信各位也看了 N 个介绍 MVVM 的文章了吧,不知道你们有没有觉得大家所描述的 MVVM 是不是...

[DAY 02] Google Apps Script

要操控google 的档案如google drive, google sheet, ...等 你除了...