一篇文章全面了解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来实现。
相关推荐
yngsqq3 分钟前
c#使用高版本8.0步骤
java·前端·c#
Myli_ing38 分钟前
考研倒计时-配色+1
前端·javascript·考研
余道各努力,千里自同风40 分钟前
前端 vue 如何区分开发环境
前端·javascript·vue.js
软件小伟1 小时前
Vue3+element-plus 实现中英文切换(Vue-i18n组件的使用)
前端·javascript·vue.js
醉の虾1 小时前
Vue3 使用v-for 渲染列表数据后更新
前端·javascript·vue.js
张小小大智慧1 小时前
TypeScript 的发展与基本语法
前端·javascript·typescript
hummhumm1 小时前
第 22 章 - Go语言 测试与基准测试
java·大数据·开发语言·前端·python·golang·log4j
asleep7012 小时前
第8章利用CSS制作导航菜单
前端·css
hummhumm2 小时前
第 28 章 - Go语言 Web 开发入门
java·开发语言·前端·python·sql·golang·前端框架
幼儿园的小霸王2 小时前
通过socket设置版本更新提示
前端·vue.js·webpack·typescript·前端框架·anti-design-vue