class组件和函数组件

我们希望编写代码的时候,尽可能将整块可复用的部分封装起来。这样可以一定程度提高代码的内聚性,将其耦合性,使得程序开发变得更加可维护。通常情况下,我们将代码块抽离成组件来实现封装。在React中,实现组件封装有两种方式,分别是通过class方式以及函数组件方式。

class方式:

class List extends React.Component {constructor(props) {super(props)}render() {const { item } = this.propsreturn <h1>{item}</h1>}
}

函数方式:

function List(props) {const { item } = propsreturn <h1>{item}</h1>
}

从上面代码中可以看出,函数组件相比于class组件要简单很多。但是函数组件1. 没有生命周期。 2. 没有state和setState,只能接收props这就导致函数组件只能实现十分基础和简单的功能,稍微复杂一点的功能只能使用class组件来实现。

使用class组件有一个不太好的地方,因为生命周期的原因,导致状态逻辑常常发生割裂。例如,组件常常在 componentDidMountcomponentDidUpdate 中获取数据。但是,同一个 componentDidMount中可能也包含很多其它的逻辑,如设置事件监听,而之后需在 componentWillUnmount 中清除。相互关联且需要对照修改的代码被进行了拆分,而完全不相关的代码却在同一个方法中组合在一起。如此很容易产生 bug,并且导致逻辑不一致[1]

由于React工具的编程理念就是在倡导函数式编程[2],但目前的函数组件功能太简单,没有办法满足更复杂的开发需求,通过引入Hook可以增强函数组件的能力,并且规避class组件不好的地方。

State Hook

默认函数组件是没有state的,函数组件是一个纯函数,执行完即销毁,无法存储state。我们如果想要扩展函数组件的功能,可以使用"钩"的办法,把state功能"钩"到纯函数中[3]。因此称之为State Hook。

关于State Hook最基本使用方式,可以看这个参考文档:使用 State Hook

Effect Hook

函数组件第二个问题是没有生命周期,和上面介绍的通过使用State Hook来向函数组件引入state一样,我们可以通过Effect Hook向函数组件引入生命周期功能。

关于Effect Hook最基本使用方式,可以看这个参考文档:使用 Effect Hook

在阅读文档的时候,你可能会像我开始的时候一样,对副作用这个词一头雾水,这里,我再对副作用这个概念做一点个人理解的简要说明。首先要明确纯函数这个概念,满足以下几点要求的函数,我们就称之为纯函数[5]

  1. 它应始终返回相同的值。不管调用该函数多少次,无论今天、明天还是将来某个时候调用它。
  2. 自包含(不使用全局变量)。
  3. 它不应修改程序的状态或引起副作用(修改全局变量)。

函数组件原本是纯函数,但使用Effect Hook之后,它可能会引起程序状态发生改变,破坏了函数组件纯函数的特点。因此我们会说,使用Effect Hook有的时候会带来副作用。比如你在函数组件生命周期里面定义了一个全局定时任务,函数组件销毁的时候却不销毁这个全局定时任务,这样就破坏了纯函数的特点,改变了整体程序状态。

最后我再说一点参考文档使用 Effect Hook中没有强调显著说明的地方。useEffect默认是模拟的DidMountDidUpdate,比如说你写成这样的形式:

useEffect(() => {console.log('我被执行啦!')
})

第一次是组件渲染的时候执行DidMount会打印该条语句,之后组件更新是执行DidUpdate组件更新又会打印该条语句。如果你只想要DidMount而不想要DidUpdate要写成这样的形式:

useEffect(() => {console.log('我被执行啦!')
}, [])

第二点是如果写成下面这种形式,每一次组件在执行更新时,都会执行前一步的卸载。useEffect会在调用一个新的 effect 之前对前一个 effect 进行清理

useEffect(() => {console.log('我被执行啦!')return () => {console.log('我被卸载啦!')}
})

useContext

通过上述两个Hook的使用,解决了函数组件最大的通点,大大增强了函数组件的能力。在官方文档的基础Hook中还有一个Hook是useContext。

它的作用就是获得父组件传递的数据。详情可以参考useContext

useReducer

useReducer是useState的替代方案,而不是替代Redux的。想了解关于Redux的更多内容可以参考: Redux 入门

关于useReducer,官方文档是这么说的:

在某些场景下,useReducer 会比 useState 更适用,例如 state 逻辑较复杂且包含多个子值,或者下一个 state 依赖于之前的 state 等。并且,使用 useReducer 还能给那些会触发深更新的组件做性能优化,因为你可以向子组件传递 dispatch 而不是回调函数 。

自定义Hook

当我们想在两个函数之间共享逻辑时,我们会把它提取到第三个函数中。而组件和 Hook 都是函数,所以也同样适用这种方式。自定义 Hook 是一个函数,其名称以 “use” 开头,函数内部可以调用其他的 Hook。其内部可以使用useState useEffect获取其他Hooks,并且可以自定义返回结果,格式不限。 关于自定义Hook具体使用可以参考:自定义 Hook

Hook使用规范

关于Hook使用规范,可以参考:Hook 规则。简单来说,一共两条:

  • 不要在循环,条件或嵌套函数中调用 Hook
  • 只在 React 函数中调用 Hook

只看文档可能不太清楚,我这里再强调一下为什么一定不要在嵌套里使用Hook。因为函数组件是一个函数,有用完即销毁的特点。那些保存的变量会被清空,是没有记忆性的。所以,如果你用了判断语句,是不能保证每次useState赋值是一致的。

参考资料

[1] Hook 简介
[2] 为什么 React 现在要推行函数式组件,用 class 不好吗?
[3] 使用 State Hook
[4] 使用 Effect Hook
[5] 什么是纯函数?它函数式编程的基础
[6] useContext
[7] Redux 入门
[8] useReducer
[9] 自定义 Hook
[10] Hook 规则

如何使用React Hook相关推荐

  1. 在React Hook里使用history.push跳转

    在React Hook里使用history.push跳转 react hook里用不了this.props.history的解决方法 首先引入 import { useHistory } from ' ...

  2. 源码解析 React Hook 构建过程

    2018 年的 React Conf 上 Dan Abramov 正式对外介绍了React Hook,这是一种让函数组件支持状态和其他 React 特性的全新方式,并被官方解读为这是下一个 5 年 R ...

  3. React Hook基本使用踩坑指南

    React因为提倡函数式编程,所以提出了Hook思想来增强函数组件的功能,以此来替代基于Class的组件.但是我们有可能从基于Class这样的实例化组件转向函数组件时思想还没有完全转过来,还是用基于实 ...

  4. react hook问题讲解

    React Hook 官网地址:https://react.docschina.org/docs/hooks-faq.html (1)问题分析? Hook 是什么? Hook 是一个特殊的函数,它可以 ...

  5. hook xposed 自定义类_【开始学习React Hook(1)】Hook之useState

    react hook是react推出的一种特殊函数.这些函数可以让你在不创建react class的情况下依然可以使用react的一些特性(诸如目前react的钩子函数拥有的所有特性). 最常用的ho ...

  6. React hook 中的数据获取

    相关说明: 对于hook相关词不翻译,感觉翻译后怪怪的. effect hook 效果钩子,用于执行一些副作用例如获取数据 . state hook 状态钩子. 使用----------- 和 --- ...

  7. slqite3库查询数据处理方式_绝活!十一个优质React Hook库, 收藏备用

    本文字数:6539字 预计阅读时间:18分钟 建议阅读方式:收藏备用 温馨提示:最近全国大幅降温,注意防寒保暖,开心跨年 长按识别,后台回复 "电子书" 即可领取<JavaS ...

  8. react讲解(函数式组件,react hook)

    文章目录 前言 一.函数式组件 理解: 作用 代码示例: 函数组件注意事项 二.React hook React Hooks 优势 Hook 使用规则 2.常用的hook useState useEf ...

  9. ref使用之react / react hook

    在react典型的数据流中,props传递是父子组件交互的一种方式:通过传递一个新的props值来使子组件重新render,从而达到父子组件通信.某些情况下(例如和第三方的dom库整合,或者某个dom ...

  10. React Hook之Effect Hook

    文章目录 Effect Hook概念性内容介绍: 如果朋友们想在里面进行异步操作的话请这样用[或者你可以把这个方法放到外面在这里调用即可]: 我们可以监听某个状态的变化来进行一些操作 useEffec ...

最新文章

  1. 下拉列表控制文本框的个数思路
  2. 后盾网lavarel视频项目---5、淘宝镜像cnpm的原理及如何使用
  3. python strip() 函数探究
  4. Cocos2d-x之绘制填充矩形
  5. web developer tips (1):创建、管理、应用样式表的强大工具
  6. 深度学习平台的未来:谁会赢得下半场?
  7. 线程 sleep 取消_C/C++ 多线程机制
  8. 程序员如何 10 分钟用 Python 画出蒙娜丽莎?
  9. 实战:kafka实现日志收集系统
  10. 从《网管员必读》系列丛书获奖看读者的真正需求——成功原因分析(一)
  11. 千万58招聘人员的选择值得信赖-米苏 58自动循环发帖器
  12. Easyui datagrid getData简单使用
  13. Visual Studio助手VAssistx各版本破解教程
  14. 驾考你准备好了吗 之 交通标志、标线篇
  15. Linux-千兆网卡驱动实现机制浅析
  16. 大奖赛现场统分(哈工大Mooc)
  17. 程序员520❤七夕情人节表白代码Html+Js+Css花瓣相册网页模板❤程序员表白必备...
  18. 狐妖小红娘的主题曲用计算机弹奏,1红娘曲谱_跪求狐妖小红娘新主题曲钢琴曲谱...
  19. 什么是外包公司,外包公司与互联网公司的区别
  20. 大学生计算机基础与实训,大学生计算机基础实训六样文.docx

热门文章

  1. Top-1 Error Top-5 Error
  2. php返回null接收的是空字符串,求大神救命!!php接收到是空的字符串
  3. 用Ant实现Java项目的自动构建和部署
  4. UITableViewCell 取消选中的蓝色背景
  5. 简单的家庭无线路由设置
  6. Markdown中常用的转义字符
  7. 【数据平台】dataframe一列成多列
  8. Java实现算法导论中Pollard的rho启发式方法
  9. Jsoup实现Iteye自动登录
  10. opencv像素基本操作及图像遍历at