1、什么是Hooks?

React Hooks是16.8之后新增一个React特性,它可以让你在函数组件中使用state等其它class组件的特性。

2、 为什么要有Hooks?

Class组件:

  • 学习成本高
  • 业务逻辑分散
  • 逻辑复用困难

Hooks:

  • 学习成本低
  • 擅长逻辑复用
  • 会产生很多闭包问题

为什么说Class学习成本高,而hooks学习成本低呢?

第一、生命周期,Class组件绕不开的一点就是生命周期的问题。React15、React16.3、React16.4到React17生命周期有了很多变化。生命周期在class组件中非常重要,面试基本都会问到。如:

  • react生命周期的变化、

  • 如何优化Class组件、

  • 一般在哪个生命周期函数中发送请求?

  • 在这个生命周期函数之前可以发送请求吗?

    第二、this指向的问题,在class组件中因为你不得不使用大量的bind或者箭头函数来定义函数。面试也会问到你:

  • 为什么要这么写?

  • 这么写的好处是什么?

  • 不这样写会产生什么问题?

对比Class,Hooks的学习成本可就太低了。基本上只要能掌握useState和useEffect,那么80%的业务问题都能解决了。

为什么说Class业务逻辑分散,而hooks擅长逻辑复用呢?

我们在学习代码的第一天,就应该知道高内聚、低耦合这六字箴言。设计组件也是一样的,我们应当考虑代码的高可复用性。然而在class组件中,我们实现一个功能,就不得不把相同业务的一些逻辑分散到各个生命周期中。

比如:

如果在组件加载的时候引入一个定时器,那么在组件卸载的时候就一定要清除这个定时器。

componentDidMount(){this.timer=setTimeout(this.fun,1000);
}
componenWillUnmount(){if(this.timer){clearTimeout(this.timer);}
}

如果我们有一个请求用户信息的组件,当用户id发生变化的时候,我们就要重新发起请求,那我们就不得不使用两个生命周期函数来处理这个发送请求的逻辑。

componentDidMount(){const {useId}=this.props;this.loadUserInfo(useId);
}
componentWillReceiveProps(nextProps){const {userId:nextUserId}=nextProps;const {userId}=this.props;if(userId!==nextUserId){this.loadUserInfo(nextUserId)}
}

注意:在React16版本这个componentWillReceiveProps被标记为unsafe之后,可以使用componentDidUpdate来代替。那么面试官可能就问你:为啥要弃用呢?

而Hooks的业务逻辑就非常聚合了。上面的例子:

useEffect(()=>{const timer=setTimeout(fun,1000);return ()=>{clearTimeout(timer);}
},[])
useEffect(()=>{loadUserInfo(userId);
},[userId])

为什么说Class复用困难,而Hooks逻辑复用简单?

​ Class组件逻辑复用一般使用的都是HOC和Render Props。但这两者虽然都可以实现逻辑复用,但是并没有让组件和代码变得好用和优美起来,这二者都会存在的一个问题是,逻辑的复用会导致嵌套层级过深,形成嵌套地狱。使用class组件,表单组件、国际化、Redux等混在一块形成一长串的高阶组件的形式大家应该都见过。

​ React Hooks很好的解决了这个问题。组件的复用,完全可以使用自定义Hooks来实现。逻辑共享也成为了社区的主流。什么是逻辑共享?众所周知,组件=UI+逻辑复用,但是当一个组件的ui完全不满足我们的需要,哪怕逻辑完全一样,这个组件的复用性也是为0。但Hooks可以帮助我们讲UI与逻辑分开,实现相同逻辑在不同组件之间的共享。

3、Hooks解决了什么问题?

React Hooks的出现解决了很多问题:

  • 函数组件有了state
  • 解决了函数式组件没有生命周期的问题
  • 解决状态逻辑难以共享的问题

React Hooks 主要解决的问题是状态逻辑共享的问题,是继render-propsHOC之后的第三种状态逻辑共享方案,它不会产生 JSX 嵌套地狱问题。状态逻辑共享其实就是状态逻辑的复用,因为它只共享和复用数据处理的逻辑,不会共享数据本身。

1) render-props:

功能: 将一个组件内的 state 作为 props 传递给调用者, 调用者可以动态的决定如何渲染.

创建 render props 的方式

  1. 接收一个外部传递进来的 props 属性
  2. 将内部的 state 作为参数传递给调用组件的 props 属性方法.
class Mouse extends React.Component {constructor(props) {super(props);this.state = { x: 0, y: 0 };}
render() {return (<div style={{ height: '100%' }}>// 使用 render props 属性来确定要渲染的内容{this.props.render(this.state)}</div>)}
}
// 调用方式:
<Mouse render={mouse => (
<p>鼠标的位置是 {mouse.x},{mouse.y}</p>
)}/>

缺点

  • 无法在 return 语句外访问数据

它不允许在 return 语句之外使用它的数据. 比如上面的例子, 不能在 useEffect 钩子或组件中的任何其他地方使用 x 和 y 值, 只能在 return 语句中访问.

  • 嵌套(有解决方案,不在这里赘述)

它很容易导致嵌套地狱. 如下代码:

const MyComponent = () => {return (<Mouse>{({ x, y }) => (<Page>{({ x: pageX, y: pageY }) => (<Connection>{({ api }) => {// yikes}}</Connection>)}</Page>)}</Mouse>)
};

2) HOC

学习 HOC 我们只需要记住以下 2 点定义,这里只做简单介绍:

  1. 创建一个函数, 该函数接收一个组件作为输入 除了组件, 还可以传递其他的参数
  2. 基于该组件返回了一个不同的组件.
function withSubscription(WrappedComponent, selectData) {returnclass extends React.Component {constructor(props) {super(props);this.state = {data: selectData(DataSource, props)};}// 一些通用的逻辑处理render() {// ... 并使用新数据渲染被包装的组件!return <WrappedComponent data={this.state.data} {...this.props} />;}};
}

优点:

不会影响内层组件的一个状态,降低了耦合度

缺点:

  • 如果,子组件的props跟父组件props相同的时候,子组件自身的 props 值可能会被父组件的props覆盖.
  • 无法清晰的标识数据的来源
  • 可能会产生嵌套地狱

3) Hooks

Hooks也是用来解决状态逻辑共享的问题的。React Hooks 就像一个内置的打平 renderProps 库,我们可以随时创建一个值,与修改这个值的方法。看上去像 function 形式的 setState,其实这等价于依赖注入,与使用 setState 相比,这个组件是没有状态的

function App() {const [open, setOpen] = useState(false);return (<><Button type="primary" onClick={() => setOpen(true)}>Open Modal</Button><Modalvisible={open}onOk={() => setOpen(false)}onCancel={() => setOpen(false)}/></>);
}
优点:
  • hook 可以重命名
  • hook 会清晰地标注数据的来源
  • hook 可以让你在 return 之外使用数据
  • hook 不会嵌套
  • hook的更新数据和状态的粒度要更细更小
  • 简单易懂, 对比 hoc 和 render props 两种方式, 它非常直观, 也更容易理解.
缺点:
  • 会产生闭包问题
  • 对人员素质有了更高的要求,React Hooks模糊了(或者说是抛弃了)生命周期的概念,看似降低了学习门槛,其实是对开发人员的素质有了一个更高的提升,它带来了更高的学习心智(如Hooks生命周期的理解、Hooks Rules的理解、useEffect依赖项的判断等),相比Vue3.0即将推出的Hooks有较高的使用门槛。
  • Hooks能解决组件功能复用,但没有很好地解决JSX的复用问题。
  • 类拥有比函数更丰富的表达能力(OOP),React采用Hooks+Function Component(函数式)的方式其实是一种无奈的选择,试想一个挂载了十几个方法或属性的Class Component,用Function Component来写如何组织代码使得逻辑清晰?这背后其实是函数式编程与面向对象编程两种编程范式的权衡

一、Hooks入门介绍相关推荐

  1. .NET读写Excel工具Spire.Xls使用(1)入门介绍

    原文:[原创].NET读写Excel工具Spire.Xls使用(1)入门介绍 在.NET平台,操作Excel文件是一个非常常用的需求,目前比较常规的方法有以下几种: 1.Office Com组件的方式 ...

  2. 独家 | 集成学习入门介绍

    作者:Jason Brownlee 翻译:wwl 校对:王琦 本文约3300字,建议阅读8分钟. 本文介绍了我们在生活中的许多决定包括了其他人的意见,由于群体的智慧,有的时候群体的决策优于个体.在机器 ...

  3. SpringBoot 2.0 系列001 -- 入门介绍以及相关概念

    为什么80%的码农都做不了架构师?>>>    SpringBoot 2.0 系列001 -- 入门介绍以及相关概念 什么是SpringBoot? 项目地址:http://proje ...

  4. ECC加密算法入门介绍

    作者  : ZMWorm[CCG]   E-Mail: zmworm@sohu.com   主页  : Http://ZMWorm.Yeah.Net/ 前言 同RSA(Ron Rivest,Adi S ...

  5. [翻译][1.4.2]Flask-Admin入门介绍

    为什么80%的码农都做不了架构师?>>>    #Flask-Admin入门介绍 ##让我们荡起双桨 初始化 Introduction To Flask-Admin Getting ...

  6. 谷歌大脑科学家亲解 LSTM:一个关于“遗忘”与“记忆”的故事 本文作者:奕欣 2017-01-14 09:46 导语:AI科技评论保证这是相对通俗易懂的一篇入门介绍了,看不懂的话欢迎关注「AI 科技

    谷歌大脑科学家亲解 LSTM:一个关于"遗忘"与"记忆"的故事 本文作者:奕欣 2017-01-14 09:46 导语:AI科技评论保证这是相对通俗易懂的一篇入 ...

  7. Tomcat容器入门介绍

    Tomcat容器入门介绍 Tomcat环境配置 PS:JDK的安装这里就不讲了,找到安装包直接下一步下一步就行了. 1.配置JDK 在Windows10下,找到环境变量 在环境变量中添加JDK主目录 ...

  8. QWT中Qdial的入门介绍

    最近使用了一下QWT.因为是第一次使用,所以有一些需要注意的地方,特记录在此,以供后来者参考. 1,QWT的安装与配置环境 有关QWT的安装与配置,网络上已经有很多篇文章,这里就不再重复了.介绍一下自 ...

  9. Spring入门介绍:

    Spring入门介绍 Spring诞生: 创建Spring的目的就是用来替代更加重量级的的企业级Java技术 简化Java的开发 基于POJO轻量级和最小侵入式开发 通过依赖注入和面向接口实现松耦合 ...

最新文章

  1. 『非常重要』非矿工用户如何安全度过BCH11月算力战历史时刻!
  2. Python函数内置函数
  3. IPv6推进将非常漫长
  4. 如何清除浮动(float)所带来的影响
  5. 使用AspectJ注解技术实现AOP功能
  6. 【国科大】计算机类课程点评(更新中)
  7. JavaFX的webview下载文件的一种实现思路
  8. Verilog HDL实现智能药盒
  9. keil数字钟c语言,在 keil 中完成数字钟的演示
  10. python 建站 上传文件_Python sdk上传
  11. CapstoneCS5211|CS5211电路|CS5211中文规格书|CS5211设计eDP到LVDS转接板/转换器方案
  12. Apple Pay初探
  13. 查看计算机.net环境版本,电脑怎么查看.NET Framework版本号?
  14. 用Java写了一个简单的控制台狼人杀游戏
  15. echarts地图生成
  16. 一文了解SAP IBP是什么?
  17. twitter APi的使用与twitter数据的应用
  18. Android--Telephony
  19. 高级Java开发招聘
  20. php Session失效的原因

热门文章

  1. android4.4默认输入法设置
  2. 千里走单骑:01-北京到上海骑记之前言
  3. 【每日一练】100—一个渐变色计数器列表的实现
  4. 【代码模板】simHash算法文本查重(golang代码实现)
  5. NOIP提高组初赛知识点解析错题本
  6. 数模--一元线性回归模型建立、matlab实现
  7. JAVA实验6继承与接口,java实验6继承与接口
  8. 特斯拉4万亿美元的【市值目标】将是一个巨大的危险信号
  9. 病历开发SDK:TX Text Control ActiveX 31.x Crack
  10. C# 最佳做法--- C# 中 SOLID 原则