在 React component 做資料 fetch、subscription、或手動改變 React component 中的 DOM 都是 side effect操作。這些操作就是程式語言中經常看到的Side Effects(副作用)(或簡稱 effect)。
Side Effect(副作用)也就是除了主要的作用外,會產生額外的其他作用,現在經常會出現在很多進階使用的JavaScript框架或函式庫之中。
我們透過使用useEffect Hook,在 component 中放置 useEffect 讓我們可以直接從component 內部呼叫 useEffect中存取 count state 變數(或任何 props)。透過使用這個 Hook,告訴 React component 需要在 render 後做一些事情。React 將記住你傳遞的 function並在執行 DOM 更新之後呼叫它。可以執行資料提取或呼叫其他命令式 API。
在下面的實作中,我在component中加入useEffect,每當onClick Event被觸動,DOM的元件更新就會重新render ,就會執行 useEffect,跳出 alert()對話視窗。
import React, { useEffect, useState } from 'react'
const App = () => {
const [num,setNum] = useState(0);
useEffect(()=>{
alert(`button clicked ${num}`);
});
return (
<div>
<button onClick={()=>{
setNum (num +1);
}}>Click number {num}
</button>
</div>
)
}
export default App
你可以把 useEffect 視為React class 的生命週期方法的 componentDidMount(),componentDidUpdate() 和 componentWillUnmount() 的組合。
如果用React class 的生命週期方法來執行Side Effect,因在 React class component 中,render 方法本身不會觸發 side effect。如果我們希望在 React 更新 DOM 之後執行我們的 side effect。必需將 side effect 放入 componentDidMount() 和 componentDidUpdate()中,告知React Component 當元件被加入到 DOM 中時或當元件的 props 或 state 更新時,重新渲染 (re-rendered) DOM ,觸發執行 side effect。
回到之前的實作中,如果用React class的方法必需把 alert() 放入componentDidMount() 和 componentDidUpdate()中,才能執行。
class Example extends React.Component {
constructor(props) {
super(props);
this.state = {
num: 0
};
}
componentDidMount() {
alert(`button clicked ${this.state.num}`)
}
componentDidUpdate() {
alert(`button clicked ${this.state.num}`)
}
render() {
return (
<div>
<button onClick={() => this.setState({ num: this.state.num + 1 })}>
Click number {this.state.num}
</button>
</div>
);
}
}
所以使用useEffect Hook的方式,每次在更新 DOM重新render之後都會執行Side effect這樣的特性,操作和時效上更優。