一、React Hooks(鉤子)是什麼
React哲學:一切皆元件
類元件
class Counter extends Component {
render () {
return "Hello World"
}
}
複製程式碼
函式元件
const Counter = () => {
return "Hello World"
}
複製程式碼
為什麼說函式式元件更優?
- 簡單易懂
- 更符合React哲學,可以理解為React就是一個畫UI的工具,符合UI=f(state)的原則
- 函數語言程式設計
有hooks之前,為什麼React需要類元件?
- 需要狀態(state)
class Counter extends Component {
state = {
count: 0
}
}
複製程式碼
- 需要生命週期函式
shouldComponentUpdate () { // 減少render渲染
return true
}
複製程式碼
- 需要副作用操作(非純函式)
副作用:呼叫ajax等
純函式:每次輸入的引數一樣,那麼每次返回的結果都相同。不要改全域性變數,不要做ajax請求,不要去做非同步操作等
componentDidMount () {
fetchAPI().then(res => {
this.setState({count: res})
})
}
複製程式碼
能否讓函式元件擁有這些功能?
const Counter = () => {
return `
想擁有,可是我沒辦法擁有狀態,也沒有生命週期函式,更不要說副作用操作了
`
}
複製程式碼
Hooks擁有了這些功能
useState 狀態管理
useEffect 生命週期函式
useContext
等等...
複製程式碼
二、React Hooks帶來哪些好處
useState: 在函式中管理狀態
const Counter = () => {
const [count, setCount] = useState(0) // 解構 初始值0
const increment = () => setCount( count + 1 )
return (
<>
<h1>{count}</h1>
<button onClick={increment}>+</button>
</>
)
}
複製程式碼
useState的返回值是什麼?
const [count, setCount] = useState(0)
可以改為下面的寫法:
const state = useState(0)
const count = state[0]
const setCount = state[1]
複製程式碼
三、常用 Hooks 使用技巧
HoC : Higher order Component(With開頭)
有了useState這個hook之後,就可以在元件裡管理狀態了
useState 一般寫在函式的最上面
useState:返回結果可以任意取名
const [count, setCount] = useState(0)
也可寫成
const [count, updateCount] = useState(0)
useState是怎麼做到的?
想象一下React為每一次useState呼叫分配一個“空間”
React通過useState呼叫順序辨別各個“空間”,很簡單,就是通過呼叫順序來區分的!
複製程式碼
useState執行順序必須一致!
不能寫在if判斷裡,如下
const Counter = () => {
const [count, setCount] = useState(0)
if (count % 2 === 0) {
const [bar, setBar] = useState(null) // 不能這麼寫
}
const [foo, setFoo] = useState("foo")
}
const [count, setCount] = useState(0) // 兩個useState 根據呼叫順序區分
const [name, setName] = useState("Fruit Bro") // 兩個useState 根據呼叫順序區分
setCount(count + 1)
setCount也是非同步的,是setState的變種!
複製程式碼
useEffect:有機會做副作用操作
componentDidMount 用於在mount過程結束時的副作用
componentDidUpdate 用於在update過程結束時的副作用
useEffect = componentDidMount + componentDidUpdate
複製程式碼
useEffect模擬componentDidMount
useEffect(() => {
// 每次mount或update都會呼叫到這裡
})
useEffect(() => {
// 只有mount時呼叫這裡
},[]) // []代表依賴的資料
複製程式碼
useEffect模擬componentDidUnmount
useEffect(() => {
// 只有mount時呼叫這裡
return () => {
// 只有unmount時呼叫這裡
}
},[])
複製程式碼
hooks特有而類元件沒有的是componentDidUnupdate,類似componentDidUnmount
useEffect模擬componentDidUpdate
const mounted = useRef() // useRef()不管呼叫多少次,返回的結果完全是一樣的
useEffect(() => {
if (!mounted.current) {
// 初次mounted,其實有用的就是current
mounted.current = true
} else {
// do componentDidUpdate logic
}
})
複製程式碼
ref可以訪問真正的dom,但在React中,是非常介意直接操作真實DOM的,因此用vitural dom
注意:每一次渲染都有獨立的props和state,每一次渲染使用hooks,函式元件的每一次渲染,無論是mount還是update,不管是第幾次update,它都有獨立的props和state
const Counter = () => {
const [count, setCount] = useState(0)
const onClick = () => {
setCount(count + 1)
setTimeout(() => {
// 返回0的原因,初次為0,只有再次渲染的時候count才會為1,而每次渲染都有獨立的props和state,因此新的渲染不會影響上一次的值
alert(count) // 0 每一次新的執行就是一次新的開始
}, 1000)
}
return (
<>
<h1>{count}</h1>
<button onClick={onClick}>+</button>
</>
)
}
複製程式碼
useContext: 簡化Context的使用
Hooks之前
<Context.Consumer>
{contextValue => <h1>{contextValue}</h1>}
</Context.Consumer>
Hooks之後
const contextValue = useContext(Context)
<h1>{contextValue}</h1>
複製程式碼
四、React Hooks有哪些好處
Hooks的好處
-
降低了元件的複雜性
1.1 完全使用函式元件
1.2 無需生命週期函式
1.3 更好的狀態管理
-
更好的程式碼重用性
2.1 傳統的程式碼重用方式 元件、高階元件(HoC)、render props模式
2.2 Hooks下的程式碼重用方式:函式
定製Hooks: 函式形式的程式碼重用
// Beacon 計數
const useBeacon = () => {
const [renderCount, setRenderCount] = useState(0)
useEffect(() => {
sendBeacon()
})
}
// 重用
const Foo = () => {
useBeacon();
...
}
const Bar = () => {
useBeacon();
...
}
複製程式碼
五、如何遷移到Hooks
React v16.8.0開始正式支援Hooks
原有類元件功能依然支援
業界趨勢將是向函式元件傾斜
遷移策略
瞭解Hooks
對新組建使用Hooks
逐步替換原有類元件
hooks如何處理類元件的shouldComponentUpdate來做效能優化 memo
如有錯誤,歡迎指正!謝謝!