1. 什么是hooks
A way to use state and other React features without writing a class.
React Hooks是React從v16.8引入的一種新的更簡單更方便的編寫組件的功能。hooks提供了一種可以不用寫class而直接使用state和其他React特性的能力,而且自定義hooks可以將公共邏輯抽離,使之可以在多個(gè)組件之間共享。
2. hooks的由來
hooks主要是為了解決以下3個(gè)React問題
組件帶狀態(tài)變得難以復(fù)用
復(fù)雜邏輯不用跟隨生命周期
-
解決難以理解的class
js中的this取值跟其他面向?qū)ο笳Z言都不同,是在運(yùn)行時(shí)決定的。為了解決這一痛點(diǎn),才有了箭頭函數(shù)的this綁定特性。另外何時(shí)使用class component 和 function component也是一件容易糾結(jié)的事,對于優(yōu)化方面來說,class component在預(yù)編譯和壓縮方面也比普通函數(shù)困難得多,還容易出錯(cuò)。
3. 使用
-
state hook
import { useState } from 'react' function Demo() { const [count, setCount] = useState(0) return ( <div> <p>count: { count }</p> <button onClick={() => { setCount(count + 1) }}>點(diǎn)擊</button> </div> ) }useState只有一個(gè)參數(shù),即count的初始值,可以是任意類型。如果count是對象,useState不會像setState自動合并原state,可以:setState(preV => { return { ...preV, ...updateV } // Object.assign(preV, updateV) })多個(gè)
state變量只需要多次調(diào)用useState即可... function Demo2() { const [count, setCount] = useState(0) const [fruit, setFruit] = useState('apple') ... } -
Effect hook
我們希望組件在DOM掛載和更新后執(zhí)行相同的操作,使用React Effect hooks寫法:
import React, { useEffect } from 'react' function Demo3() { const [count, setCount] = useState(0) useEffect(() => { document.title = `clicked ${count} times` }) }傳統(tǒng)class component寫法:
import React from 'react' class Demo3 extends React.Component{ constrctor(props) { super(props) this.state = { count: 0 } } componentDidMount () { document.title = `clicked ${this.state.count} times` } compoenntDidUpdate () { document.title = `clicked ${this.state.count} times` } ... }傳統(tǒng)class component,我們需要在兩個(gè)生命周期中調(diào)用相同的函數(shù),使用Effect特性React會保存?zhèn)鬟f的函數(shù),并在DOM渲染后調(diào)用該函數(shù)。
useEffect同時(shí)擁有componentDidMount,componentDidUpdate,componentWillUnmount三個(gè)生命周期的執(zhí)行時(shí)機(jī)。但Effct并不會阻塞瀏覽的渲染,使應(yīng)用看起來更加流暢。有時(shí)候我們?yōu)榱朔乐箖?nèi)存泄漏需要清除的Effct,class component中需要在
componentDIdMount中注冊并在componentWillUnmount中銷毀,使用hooks只需要在useEffct中返回一個(gè)函數(shù)即可function Demo4() { useEffct(() => { let timer = setInterval(() => { console.log(1) }) return () => { clearInterval(timer) } }) }當(dāng)
useEffct返回一個(gè)函數(shù)的時(shí)候,React會在下一次執(zhí)行副作用之前調(diào)用一次清理函數(shù)。組件掛載 —> 執(zhí)行副作用 —>組件更新 —>執(zhí)行清理函數(shù)—>執(zhí)行副作用—>組件更新—>執(zhí)行清理函數(shù)—>組件卸載
所以每次
state更新我們都會重新渲染一次,如果state值沒有改變的情況下(原來count是5改變后還是5),我們不想調(diào)用Effct,只需要在useEffct函數(shù)中傳入第二個(gè)參數(shù)[count]即可。React會對前一次渲染的[5]和后一次渲染的[5]對比,數(shù)組內(nèi)元素全部相等,React就會跳過這個(gè)Effct,同時(shí)實(shí)現(xiàn)了性能的優(yōu)化。該參數(shù)為數(shù)組,可以傳多個(gè)數(shù)組,一般會將Effct用到的props和state都傳進(jìn)去。清除函數(shù)同理。如果
useEffct傳入的第二個(gè)參數(shù)是一個(gè)[],等效于componentDidMount和componentWillUnmount
4. hooks規(guī)則
只能在
React 函數(shù)式組件中調(diào)用Hook只能在
函數(shù)最外層調(diào)用Hook只能用在
函數(shù)最頂層不能用在循環(huán)、條件判斷語句,嵌套函數(shù)
ESLint插件
eslint-plugin-react-hooks格式規(guī)范
...