React Hook 是 v16.8 的新功能,自誕生以來,受到普遍的好評,在 React 版本更新中具備里程碑的意義。如今都2020年了,再不上車 React Hook 就真的 out 了...
javascript
本着「存在即合理」的原則,咱們先來康康 Hook 爲咱們解決了哪些問題?Hook 有哪些優點呢?
在編寫 React 組件時,咱們更喜歡函數組件,而不是 class 組件。
由於函數組件代碼更少,結構更清晰,不容易產生 bug。可是,函數組件沒辦法使用狀態,只能做爲展現組件(就是個花瓶...哎)。
有了 Hook,咱們就能在函數組件中使用狀態了**。絕不誇張的說,之後的組件均可以用函數組件 + Hook 來寫。
class 組件的問題:html
componentDidMount
中註冊事件以及其餘的邏輯,在 componentWillUnmount
中卸載事件,這樣分散不集中的寫法,很容易寫出 bug )
Hook 優點:java
ajax
請求、訪問原生dom
元素、本地持久化緩存、綁定/解綁事件、添加訂閱、設置定時器、記錄日誌等。以往這些反作用都是寫在類組件生命週期函數中的。而 useEffect
在所有渲染完畢後纔會執行,useLayoutEffect
會在瀏覽器 layout
以後,painting
以前執行Hook 可讓你在不編寫 class 組件的狀況下使用 state 以及其餘的 React 特性。可是,有些規則是咱們須要準守的:
react
useState
和 useEffect
調用之間保持 hook 狀態的正確
ok,到此爲止,咱們已經瞭解 Hook 有哪些優點了。
下面,咱們開始認識最經常使用的兩個 Hook API—— useState、useEffect。
這兩個API很好理解,並且很實用,弄懂能處理80%的業務場景。本文不會涉及太複雜的操做,僅僅做爲入門。
git
先來看一段簡單的 Hook 代碼:github
import React, { useState } from 'react'; function Example() { // 聲明一個叫 "count" 的 state 變量 const [count, setCount] = useState(0); return ( <div> <p>You clicked {count} times</p> <button onClick={() => setCount(count + 1)}> Click me </button> </div> ); }
咱們將經過將這段代碼與一個等價的 class 示例進行比較來開始學習 Hook。面試
等價的 class 組件示例:ajax
class Example extends React.Component { constructor(props) { super(props); this.state = { count: 0 }; } render() { return ( <div> <p>You clicked {this.state.count} times</p> <button onClick={() => this.setState({ count: this.state.count + 1 })}> Click me </button> </div> ); } }
很簡單的一個加1計數器,Hook 寫法比 class 組件是否是簡潔了不少。
下面,咱們來分析如何使用 useState Hook...數組
// 第一步:從 react 庫中引入 useState Hook import React, { useState } from 'react'; function Example() { /* 第二步:經過調用 useState Hook 聲明瞭一個新的 state 變量。 * 它返回一對值(數組)解構到咱們命名的變量上。 * 第一個返回的是狀態 count,它存儲的是點擊次數。咱們經過傳 0 做爲 useState 惟一的參數來將其初始化 0。 * 第二個返回的值自己就是一個函數。它讓咱們能夠更新 count 的值,因此咱們叫它 setCount。 */ const [count, setCount] = useState(0); // 聲明一個叫 "count" 的 state 變量 return ( <div> // 第三步:讀取 state,即count <p>You clicked {count} times</p> // 第四步:更新 state,經過 setCount() <button onClick={() => setCount(count + 1)}> Click me </button> </div> ); }
經過上面的分析,咱們能夠看到使用 useState Hook 管理狀態簡直太爽了。不用寫繁瑣的 class 組件,不用擔憂 this 指向,代碼是如此的清晰。
如何使用多個 state 變量:
將 state 變量聲明爲一對 [something, setSomething]
也很方便,由於若是咱們想使用多個 state 變量,它容許咱們給不一樣的 state 變量取不一樣的名稱:瀏覽器
function ExampleWithManyStates() { // 聲明多個 state 變量 const [age, setAge] = useState(42); const [fruit, setFruit] = useState('banana'); const [todos, setTodos] = useState([{ text: '學習 Hook' }]); ...
在以上組件中,咱們有局部變量 age
,fruit
和 todos
,而且咱們能夠單獨更新它們:
function handleOrangeClick() { // 和 this.setState({ fruit: 'orange' }) 相似 setFruit('orange'); }
你沒必要使用多個 state 變量。State 變量能夠很好地存儲對象和數組,所以,你仍然能夠將相關數據分爲一組。然而,不像 class 中的 this.setState
,更新 state 變量老是_替換_它而不是合併它。
注意
你可能想知道:爲何叫useState
而不叫createState
?
「Create」 可能不是很準確,由於state 只在組件首次渲染的時候被建立。在下一次從新渲染時,useState
返回給咱們當前的 state。不然它就不是 「state」了!這也是 Hook 的名字_老是_以use
開頭的一個緣由。
Effect Hook定義:useEffect 傳入一個 callback 函數
useEffect(effect: React.EffectCallback, deps?: ReadonlyArray<any> | undefined)
Effect Hook做用:處理函數組件中的反作用,如異步操做、延遲操做等,能夠替代Class Component的componentDidMount
、componentDidUpdate
、componentWillUnmount
等生命週期。
Effect Hook特性:
ajax
請求、訪問原生dom
元素、本地持久化緩存、綁定/解綁事件、添加訂閱、設置定時器、記錄日誌等。componentDidMount
、componentDidUpdate
和 componentWillUnmount
具備相同的用途,只不過被合併成了一個 APIcomponentDidMount
或 componentDidUpdate
不一樣,使用 useEffect 調度的 effect 不會阻塞瀏覽器更新屏幕,這讓你的應用看起來響應更快。大多數狀況下,effect 不須要同步地執行。在個別狀況下(例如測量佈局),有單獨的 useLayoutEffect Hook 供你使用,其 API 與 useEffect 相同
useEffect 使用示例:
import React, { useState, useEffect } from 'react'; function Example() { const [count, setCount] = useState(0); // 相似 componentDidMount 和 componentDidUpdate useEffect(() => { // 使用瀏覽器 API 去更新 document 標題 document.title = `You clicked ${count} times`; }); // 相似 componentDidMount useEffect(() => { // 使用瀏覽器 API 去更新 document 標題 document.title = `You clicked ${count} times`; }, []); // 慎用!監聽空數組,當 callback 使用到 state 或 props 時最好不要用,由於只能獲取初始化的數據 // 返回一個函數用於清除操做 useEffect(() => { document.title = `You clicked ${count} times`; window.addEventListener('load', loadHandle); // loadHandle 函數定義省略 return () => { window.removeEventListener('load', loadHandle); // 執行清理:callback 下一次執行前調用 }; }, [count]); // 只有當count的值發生變化時,纔會從新執行 callback return ( <div> <p>You clicked {count} times</p> <button onClick={() => setCount(count + 1)}> Click me </button> </div> ); }
useEffect 用法很簡單,可是有兩個地方須要特別注意:
useEffect 的用法大概就是這樣的,有一些坑和更復雜操做這裏沒有涉及。固然,要深刻理解的話須要去啃源碼了,這裏不作過多的解釋。
Hook 核心知識點:閉包
當你在使用 Hook 遇到問題時,請先考慮是否因爲閉包引發的。這將幫助你快速排查問題。
Hook 讓咱們能夠在函數組件中使用狀態state,函數組件一統 React 的時代來了,這很棒。
Hook 可讓咱們摒棄那些繁瑣的生命週期、不用考慮 this 的指向、複用邏輯也不用寫HOC了,這很棒。
Hook 還有更多 API 等着咱們去探索,同時也支持自定義 Hook。
Hook 發車啦,用過都說好...
參考:
Hook 官方文檔
30分鐘精通React Hooks
React Hooks徹底上手指南