React 加入 Hooks 的意义是什么?或者说一下为什么 React 要加入 Hooks 这一特性?最后举例说一下 Hooks 的基本实现原理

发布于 2023-09-10 10:53:46 字数 3810 浏览 47 评论 0

最近看到一个关于 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 :

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​react.docschina.org

文档中的 动机 就很好的解释了为什么 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 的方式思考”前,需要做一些思维上的转变。

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据

关于作者

文章
评论
24 人气
更多

推荐作者

夢野间

文章 0 评论 0

doggiejohn

文章 0 评论 0

就此别过

文章 0 评论 0

初见终念

文章 0 评论 0

qq_rvKjBH

文章 0 评论 0

    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文