最近看到一個關於 React 的面試題,是京東技術三面的題目,感受頗有意思,一塊兒來看看:react
React 加入 Hooks 的意義是什麼?或者說一下爲何 React 要加入Hooks 這一特性?最後舉例說一下 Hooks 的基本實現原理;面試
首先,咱們看一下典型的兩個 Hooks 的基本使用,直接看代碼,這裏就不細說了;編程
useState 基本使用:數組
// 引入 useState
import React, { useState } from 'react'
function App() {
// 使用
const [count, setCount] = useState(1);
return (
<div> <h2> useState </h2> <p>{count}</p> {/* 調用 setCount方法 */} <button onClick={() => setCount(count + 1)}> 加1 </button> </div>
)
}
export default App
複製代碼
useEffect :markdown
import React, { useState, useEffect } from 'react'
import ReactDom from 'react-dom'
function App() {
const [count, setCount] = useState(1)
// 組件掛載完成以後執行 && 組件數據更新完成以後執行
// useEffect(() => {
// console.log('666')
// })
// 組件掛載完成以後執行
// useEffect(()=>{
// console.log(678)
// },[])
// 組件被卸載以前執行 (引入react-dom進行卸載測試)
useEffect(()=>{
return ()=>{
console.log('組件被卸載了')
}
})
return (
<div> <h2>useEffect</h2> <p>{count}</p> <button onClick={() => setCount(count + 1)}> 加1 </button> {/* 卸載組件 */} <button onClick={()=>ReactDom.unmountComponentAtNode(document.getElementById('root'))}>卸載組件</button> </div>
)
}
export default App
複製代碼
回到前面的問題,其實這樣的問題並無什麼標準答案,可是咱們能夠換位思考,站在面試官的角度想一下,爲何會問這樣的問題?無非就是想考察咱們對 Hooks 最基本的使用狀況以及對 Hooks 設計理念的我的思考; 其實在 React 官方文檔中,已經給出了答案,奈何不少人就是不看文檔啊; Hook 簡介 – React (docschina.org)dom
文檔中的 「動機」 就很好的解釋了爲何 React 要加入 Hooks 特性,總結來講就是三個基本要素: 1:組件之間的邏輯狀態難以複用; 2:大型複雜的組件很難拆分; 3:Class 語法的使用不友好;函數式編程
總的來講,實際上就是類組件在多年的應用實踐中,發現了不少沒法避免問題而又難以解決,而相對類組件,函數組件又太過於簡陋,好比,類組件能夠訪問生命週期方法,函數組件不能;類組件中能夠定義並維護 state(狀態),而函數組件不能夠;類組件中能夠獲取到實例化後的 this,並基於這個 this 作各類各樣的事情,而函數組件不能夠;函數
可是,函數式編程方式在JS中確實比 Class 的面向對象方式更加友好直觀,那麼只要可以將函數的組件能力補齊,也就解決了上面的問題,而若是直接修改函數組件的能力,勢必會形成更大的成本,最好的方式就是開放對應接口進行調用,非侵入式引入組件能力,也就是咱們如今看到的 Hooks 了;學習
明白了與緣由,面試中的問題也就迎刃而解了,基本思路就是先闡述在沒有 Hooks 的時候,類組件有哪些問題,函數組件有哪些不足,而 Hooks 就是解決這些問題出現的;這也就是 Hooks 出現的意義了,那麼接着,咱們再來解答下一個問題,Hooks 的設計理念是什麼呢? 咱們先用代碼來模仿一個基本的 Hooks 的實現過程,重寫 useState :測試
import React from 'react'
// 導入dom,用於更新組件
import ReactDom from 'react-dom'
let state
function useState(initState) {
// 判斷state 是不是初始化
state = state ? state : initState
function setState(newState) {
// 更新數據
state = newState
// 調用函數,更新組件
render()
}
return [state, setState]
}
// 從新渲染組件
function render() {
ReactDom.render(<App />, document.getElementById('root'))
}
function App() {
// 使用自定義 useState
const [count, setCount] = useState(1);
return (
<div> <p>{count}</p> <button onClick={() => setCount(count + 1)}>加1</button> </div>
)
}
export default App
複製代碼
Rudi Yardley 在 2018 年的時候寫過一篇文章 《React hooks: not magic, just arrays》,詳細地闡釋了它的設計原理,感興趣的話能夠找來看一下,上面案例,其實就是文章中用到的,經過在函數中調用 useState 會返回當前狀態與更新狀態的函數。count 的初始值是 1,而後,經過 useState 賦值初始值,而後獲取當前狀態 state 與函數 setState。那麼在點擊按鈕時調用 setCount,修改 count 的值。本質上 state hook 替代了類組件中 setState 的做用。
通常狀況下,一段激情的闡述以後都是要上價值的,因此,咱也來一段;
React 團隊固然清楚,新加一個全新的概念,對咱們開發者來講是一個很高的學習成本,所以官方爲好奇的讀者準備了 詳細的徵求意見文檔,在文檔中用更多細節深刻討論了 React 推動這件事的動機,也在具體設計決策和相關先進技術上提供了額外的視角。
最重要的是,Hook 和現有代碼能夠同時工做,你能夠漸進式地使用他們。 不用急着遷移到 Hook。咱們建議避免任何「大規模重寫」,尤爲是對於現有的、複雜的 class 組件。開始「用 Hook 的方式思考」前,須要作一些思惟上的轉變。