最近看到一个关于 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 的方式思考”前,须要作一些思惟上的转变。