一篇文章全面了解React-Hooks

在讲react hooks之前,我们应该先了解一下react组件的两个概念。即有状态组件和无状态组件。

  • 有状态组件(类组件)

在前面的学习过程中我们掌握了类组件的创建,在React中类组件被称之为有状态组件。我们使用继承自React.Component的类来创建React组件,在类组件中我们拥有Props ,控制状态的State, 可以使用生命周期函数

其中Props能够帮助我们完成React组件间的传参 ,通信等工作。我们使用积木式的方式搭建一个复杂页面,那么我们所使用的父组件和子组件之间肯定会有这千丝万缕的联系。一般我们可以总结为3种组件的通信关系:父子组件的通信,子父组件的通信以及兄弟组件的通信。目前我们只需要了解Props是帮助组件间进行通信即可,后面我们会详细展开并通过实际的案例帮助我们更深刻的理解Props。

State是用来表示组件的状态 ,可以帮助我们所创建的组件动起来。如果你希望在用户对页面进行操作之后对应页面UI做到动态更新,我们就可以使用State来控制组件的状态当我们程序判断出组件状态发生改变UI就会自动更新。在React中我们使用setState方法对组件的状态进行更新。

最后React生命周期函数是一组钩子函数,这些函数在组件的各个不同的时期会被触发。React的生命周期会由组件加载完成阶段,组件更新阶段,组件销毁阶段等一系列阶段所组成。这些生命周期函数能给帮助我们完成很多的工作例如状态的更新,数据的请求,页面的局部渲染等。

  • 无状态组件(函数组件)

在React中将函数组件 称之为无状态组件,它没有自己的状态只负责数据的展示。如果你的组件只需要做静态页面的展示而没有复杂的用户交互以及状态更新,我们推荐使用函数组件就行。因为在运行状态组件(类组件)时,会触发生命周期中的一些函数,并且状态的更新会导致我们页面组件反复重新渲染(因为状态的改变会导致页面UI更新,所以需要重新渲染组件)。如果我们构建的组件不需要对状态进行存储,修改等操作的话使用无状态组件的效率会更高并且可以避免意想不到的问题。


上面笼统的介绍了react的有状态组件和无状态组件的概念。言归正传说回react-hooks

从上述的介绍中我们可以得出,函数组件内部无法定义和维护State,那么react-hooks的出现为函数组件赋予了数据管理的功能。

然后我们来明确一下两者之间的对比:无关优劣,只有不同

  • 类组件需要继承Class,函数组件不需要
  • 类组件可以访问生命周期函数,函数组件不能
  • 类组件可以定义并维护state,函数组件不能
  • 类组件可以实例化this,并基于这个this做操作,函数组件不能

如果单从区别上就判定类组件优于函数组件这个是不准确的,只能说在React-Hooks出来之前,类组件的能力边界是优于函数组件的。当我们在讨论两个组件时,不应该重点对比两者之间哪个更好哪个不好,而是关注这两者的区别。

类组件

  • 前面提到了类组件是面向对象的一种表现形式,面向对象最常做的两个事情就是继承和封装,React中也不例外。
  • 在类组件中,React在内部预置了很多现成的东西等待去学习和使用,State和生命周期就是React中预置好的现成东西的典型。所以当我们需要使用这些内容的时候,只需要调用一个React.components 就可以了。也正是因为这些现成的东西,这种大而全的模式加大了我们对于类组件的学习和使用成本。
  • 由于类组件的这种模式会将开发者编写的逻辑在封装后与组件强制粘在一起,所以对于组件内的逻辑很难做到拆分和复用。如果想要做到这些,就需要再去学习更加复杂的设计模式,例如React的高阶组件、Render Props等

函数组件

  • -相对于类组件来说,函数组件最明显的就是代码更加轻量、灵活、易于维护、更加易懂。函数组件就是我们前端最基础的函数式编程的表现形式。函数组件是更加贴合React框架设计理念的一种编程手法。React组件本身就是函数,一个吃进数据,吐出UI试图的函数。
  • 由于函数组件中无法定义和维护State,并且没有生命周期这一概念。为了使函数组件更加强大,有了React-hooks,React-hooks提供了更灵活的钩子函数。
  • useState引入了对state状态的管理,useEffect某种程度上面代替了生命周期,允许函数组件执行副作用事件。

useEffect三种情况:

  1. 等价于生命周期中的:mounted。 每一次渲染后执行,则传入回调函数,不传入依赖数组。写法:useEffect(callBack, \[\])。 第二个参数放置一个空\[\]。
js 复制代码
 useEffect(() => {
    console.log('组件创建渲染之后执行')
  }, [])
  1. 等价于生命周期中的:update。useEffect(callback, \[\]), 第二个参数需要传入被依赖的state变量,当数据发生变化时,才会触发callBack的执行。写法如下:
js 复制代码
 useEffect(() => {
    console.log('[]中放置依赖的数据,依赖数据发生变化时,触发useEffect')
  }, [a,b,c])
  1. 等价于生命周期中的:Unmount。useEffect同时也可以等价于卸载阶段会被触发的副作用。传入回调函数,且这个函数的返回值是一个函数,同时不传第二个参数。
js 复制代码
useEffect(()=>{ 
    // 这里是 A 的业务逻辑 
    useEffect(() => {
    console.log('等价于生命周期中的mounted会执行的函数内容')

    // 返回一个函数记为 B 
    return () => {
      console.log('等价于生命周期中的Unmounted会执行的函数内容')
    }
  }, [])
}) 
// 上面这段代码就会使得 React 在每一次渲染都去触发 A 逻辑,并且在卸载阶段去触发 B 逻辑。 
// 其实你只要记住,如果你有一段副作用逻辑需要在卸载阶段执行
// 那么把它写进 useEffect 回调的返回函数(上面示例中的 B 函数)里就行了。 
// 也可以认为,这个 B 函数的角色定位就类似于生命周期里 componentWillUnmount 方法里的逻辑

为什么需要React-Hooks? And... Hooks 是如何帮助我们升级工作模式的 以下 4 条思路:

  1. 告别难以理解的 Class;
  2. 解决业务逻辑难以拆分的问题;
  3. 使状态逻辑复用变得简单可行;
  4. 函数组件从设计思想上来看,更加契合 React 的理念。(上面已做解答)

问题1:

  • 在之前的学习过程中,对于Class的理解就有些晦涩难懂,在React类组件中我们也会因为this的获取不正确导致代码报错。
  • 关于生命周期还有两个麻烦的点就是:1、学习成本,2、不合理的逻辑规划。

问题2:

  • 在类组件中,我们通常要将我们的业务逻辑与不同的生命周期函数想结合来实现。像这种开发模式会导致代码体积过大,逻辑分布分散。

问题3:

  • 在类组件的开发模式中,我们如果要复用状态逻辑,需要借助于高阶组件或者是render props的设计模式。但这种设计模式方式来实现逻辑复用的弊端就是会造成"嵌套地狱"。
  • 在React hooks中可以通过自定义hooks来实现。
相关推荐
格子软件38 分钟前
2026年GEO优化系统源码级状态机与多模型调度拆解
java·前端·vue.js·人工智能·vue·geo
HUMHSX1 小时前
Vue 项目启动全流程解析:从入口文件到全局指令注册与页面渲染
前端·javascript·vue.js
有颜有货2 小时前
PMC生产排产的4种算法,一次讲清
java·服务器·前端
小虎牙0072 小时前
Android kotlin图片库Coil源码详解
android·前端
随风一样自由2 小时前
【前端领域】前端开发核心应用场景与落地实践
前端·前端框架
an317422 小时前
弹窗数据流设计的两种高阶架构实践
前端·vue.js·架构
谢尔登2 小时前
【React】 状态管理方案
前端·react.js·前端框架
用户2136610035723 小时前
Vue商品详情与放大镜组件
前端·javascript
半个落月3 小时前
从Tapas小Demo理清localStorage、事件与this
前端·javascript
李明卫杭州3 小时前
Vue2 中 v-model 处理不同数据结构的技巧
前端·javascript·vue.js