一篇文章全面了解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来实现。
相关推荐
加班是不可能的,除非双倍日工资13 分钟前
css预编译器实现星空背景图
前端·css·vue3
wyiyiyi1 小时前
【Web后端】Django、flask及其场景——以构建系统原型为例
前端·数据库·后端·python·django·flask
gnip1 小时前
vite和webpack打包结构控制
前端·javascript
excel1 小时前
在二维 Canvas 中模拟三角形绕 X、Y 轴旋转
前端
阿华的代码王国2 小时前
【Android】RecyclerView复用CheckBox的异常状态
android·xml·java·前端·后端
一条上岸小咸鱼2 小时前
Kotlin 基本数据类型(三):Booleans、Characters
android·前端·kotlin
Jimmy2 小时前
AI 代理是什么,其有助于我们实现更智能编程
前端·后端·ai编程
ZXT2 小时前
promise & async await总结
前端
Jerry说前后端2 小时前
RecyclerView 性能优化:从原理到实践的深度优化方案
android·前端·性能优化
画个太阳作晴天2 小时前
A12预装app
linux·服务器·前端