一開始學習 React.js 一定會學到的東西就是 React Hook,不過 React Hook 到底是啥?我們為什麼要用它?
React Hook 是什麼
在 React 16.8 中引入了一個全新的概念,稱為「Hook」,Hook 是一些特殊的function,它讓你不必寫 class 就能夠掛勾 state (狀態) 以及其他 React 的功能。簡單來說就是一個新一代的 React API 啦~
為什麼要有 React Hook
在還沒有 React hook 以前,使用 React 開發的當時遇到了 3 個大問題:Reusing Logic、Giant Components、Confusing Classes
- Reusing logic:為了重複使用相同的程式邏輯,當時的做法是透過 HOC 和 Render Props 來解決這個問題,但這反而造成了"波動拳"問題 (Wrapper Hell)
- Giant Components:以前 React 主要是用 class 建構的,生命週期會長這樣:
這樣的架構下限制了不同的程式邏輯必須擠在同一個 lifecycle function 裡面,當程式邏輯變得越複雜,lifecycle function 也會變得越來越龐大,不相干的程式邏輯都會擺在一起難以維護。
再來就是很難偵錯,如果在componentDidMount
訂閱了某個方法,而忘記在componentWillUnmount
取消訂閱,則會導致 memory leak,很難直接偵錯出來。
- Confusing Classes:就是 Class 還有
this
的指向常常讓人搞混,此外 ReactJS 的開發團隊也發現 ES6 class 會影響 compile 的效能。
React hook vs class
不囉嗦 還是直接看 code 最清楚:
Class 的寫法
import React, { Component } from "react";
class Example extends Component {
state = {
Count: 0,
};
componentDidUpdate(prevProps, prevState) {
if (prevState.Count !== this.state.Count) {
console.log("Count update");
}
}
handleClick = () => {
this.setState((prevState) => ({ count: prevState.count + 1 }));
};
render() {
return (
<div>
<p>Click: {this.state.count}</p>
<button onClick={this.handleClick}>click</button>
</div>
);
}
}
get 及 set: 在 Class 寫法中,我們使用 this.state.count 來獲取狀態的值,並使用 this.setState 來設定狀態的新值。
Count 更新的生命週期: 在 Class 寫法中,我們使用 componentDidUpdate 生命週期方法來偵測 count 狀態的更新,並執行相應的操作。
Template 取得變數: 在 Template 中,我們使用 this.state.count 來取得 count 狀態的值。
React hook 的寫法
import React, { useState, useEffect } from "react";
function Example() {
const [count, setCount] = useState(0);
useEffect(() => {
console.log("Count update");
}, [count]);
const handleClick = () => {
setCount((prevCount) => prevCount + 1);
};
return (
<div>
<p>Click: {count}</p>
<button onClick={handleClick}>click</button>
</div>
);
get 及 set: 使用 React Hook 的方式,我們使用 useState Hook 來定義狀態變數 count 和設定函數 setCount,然後初始化為 0。不再需要一個包含所有狀態的物件,每個狀態可以獨立管理。
Count 更新的生命週期: 使用 React Hook,我們使用 useEffect Hook 來偵測 count 狀態的更新,只有在 count 有變化時才會執行 console.log("Count update")。
Template 取得變數: 在 Template 中,我們可以直接使用 count 來取得 count 狀態的值,不再需要使用 this.state.count。