一、Hooks入门介绍
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-props和 HOC之后的第三种状态逻辑共享方案,它不会产生 JSX 嵌套地狱问题。状态逻辑共享其实就是状态逻辑的复用,因为它只共享和复用数据处理的逻辑,不会共享数据本身。
1) render-props:
功能: 将一个组件内的 state 作为 props 传递给调用者, 调用者可以动态的决定如何渲染.
创建 render props 的方式
- 接收一个外部传递进来的 props 属性
- 将内部的 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 点定义,这里只做简单介绍:
- 创建一个函数, 该函数接收一个组件作为输入 除了组件, 还可以传递其他的参数
- 基于该组件返回了一个不同的组件.
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入门介绍相关推荐
- .NET读写Excel工具Spire.Xls使用(1)入门介绍
原文:[原创].NET读写Excel工具Spire.Xls使用(1)入门介绍 在.NET平台,操作Excel文件是一个非常常用的需求,目前比较常规的方法有以下几种: 1.Office Com组件的方式 ...
- 独家 | 集成学习入门介绍
作者:Jason Brownlee 翻译:wwl 校对:王琦 本文约3300字,建议阅读8分钟. 本文介绍了我们在生活中的许多决定包括了其他人的意见,由于群体的智慧,有的时候群体的决策优于个体.在机器 ...
- SpringBoot 2.0 系列001 -- 入门介绍以及相关概念
为什么80%的码农都做不了架构师?>>> SpringBoot 2.0 系列001 -- 入门介绍以及相关概念 什么是SpringBoot? 项目地址:http://proje ...
- ECC加密算法入门介绍
作者 : ZMWorm[CCG] E-Mail: zmworm@sohu.com 主页 : Http://ZMWorm.Yeah.Net/ 前言 同RSA(Ron Rivest,Adi S ...
- [翻译][1.4.2]Flask-Admin入门介绍
为什么80%的码农都做不了架构师?>>> #Flask-Admin入门介绍 ##让我们荡起双桨 初始化 Introduction To Flask-Admin Getting ...
- 谷歌大脑科学家亲解 LSTM:一个关于“遗忘”与“记忆”的故事 本文作者:奕欣 2017-01-14 09:46 导语:AI科技评论保证这是相对通俗易懂的一篇入门介绍了,看不懂的话欢迎关注「AI 科技
谷歌大脑科学家亲解 LSTM:一个关于"遗忘"与"记忆"的故事 本文作者:奕欣 2017-01-14 09:46 导语:AI科技评论保证这是相对通俗易懂的一篇入 ...
- Tomcat容器入门介绍
Tomcat容器入门介绍 Tomcat环境配置 PS:JDK的安装这里就不讲了,找到安装包直接下一步下一步就行了. 1.配置JDK 在Windows10下,找到环境变量 在环境变量中添加JDK主目录 ...
- QWT中Qdial的入门介绍
最近使用了一下QWT.因为是第一次使用,所以有一些需要注意的地方,特记录在此,以供后来者参考. 1,QWT的安装与配置环境 有关QWT的安装与配置,网络上已经有很多篇文章,这里就不再重复了.介绍一下自 ...
- Spring入门介绍:
Spring入门介绍 Spring诞生: 创建Spring的目的就是用来替代更加重量级的的企业级Java技术 简化Java的开发 基于POJO轻量级和最小侵入式开发 通过依赖注入和面向接口实现松耦合 ...
最新文章
- 『非常重要』非矿工用户如何安全度过BCH11月算力战历史时刻!
- Python函数内置函数
- IPv6推进将非常漫长
- 如何清除浮动(float)所带来的影响
- 使用AspectJ注解技术实现AOP功能
- 【国科大】计算机类课程点评(更新中)
- JavaFX的webview下载文件的一种实现思路
- Verilog HDL实现智能药盒
- keil数字钟c语言,在 keil 中完成数字钟的演示
- python 建站 上传文件_Python sdk上传
- CapstoneCS5211|CS5211电路|CS5211中文规格书|CS5211设计eDP到LVDS转接板/转换器方案
- Apple Pay初探
- 查看计算机.net环境版本,电脑怎么查看.NET Framework版本号?
- 用Java写了一个简单的控制台狼人杀游戏
- echarts地图生成
- 一文了解SAP IBP是什么?
- twitter APi的使用与twitter数据的应用
- Android--Telephony
- 高级Java开发招聘
- php Session失效的原因