4届中国前端开发者大会 · 2019. 5. 13. · react class-component 只用到了 es2015 class...

Post on 19-Aug-2020

14 Views

Category:

Documents

0 Downloads

Preview:

Click to see full reader

TRANSCRIPT

第4届中国前端开发者大会

React-Hooks: 从设计理念到实战经验

演讲者:李子翔

目录 CONTENTS React-Hooks 出现的背景

React-hooks 实战

React-Hooks 使用中的问题

探索 React-Hooks 内部

1 React-Hooks 出现的背景class-component 的问题

class-component 只是过度方案

在组件之间复用有状态逻辑很困难

如果你使用过 React 一段时间,你也许会熟悉一些解决此类问题的方案,比如 render props 和 hoc。但是这类方案需要重新组织你的组件结构,这可能会很麻烦,使代码难以理解。

组件复杂后变得难以理解

相互关联且需要对照修改的代码被进行了拆分,而完全不相关的代码却在同一个方法中组合在一起。

class-component 是过度方案

React class-component 只用到了 ES2015 class 最初级的特性

然而,有了 Hooks 以后,我们几乎就不需要 super 和 this 了

class-component 是过度方案

不建议组件继承非 React.Component | React.PureComponent

React 推崇 HOC 和组合的方式,而不是继承的方式来扩展组件

组合更适合React的风格,因为React是基于组件的

因此 React 从未把 class-component 视为最终的组件定义方式

2 React-hooks 实战本次实战将演示

从Class-Component转变到Hooks再到Custom-Hooks的写法

Demo效果预览

本案例包含了监听窗口变化、监听

鼠标移动事件、监听Hash变化、使

用Context 来传递国际化数据,并

教大家如何从Class-Component迁

移到Hooks上,最终再抽取出

Custom Hooks来进行代码的复用。

Demo效果

Demo源码

应用的主体结构

分别使用 3种 写法的组件来实现效果

监听Hash变化来呈现不同的实现

使用Context来传递国际化数据

Class-Component

更新Document Title定义State

处理窗口Resize事件 处理鼠标移动事件

Class-Component 中生命周期的处理

组件加载完成后:

更新Document Title

监听 Resize事件

监听 Mouse Move 事件

组件更新时:

更新Document Title

组件销毁前:

移除事件监听

Render 函数

获取数据

根据位置计算Css3属性

遍历出人物卡片

改写为Hooks

初始化状态

改写为Hooks

更新Title

改写为Hooks

处理Resize事件

改写为Hooks

处理鼠标移动事件

Return的组件

虽然使用了Hooks改写了我们

的组件,但是并没有解决核心

问题:状态逻辑的复用

使用 Custom-Hooks 后的 Card 组件

状态与UI的界线变的清晰

我们只需要使用useXXX来得到

数据。

通过Custom-Hooks我们可以

在现有的所有组件中引用他们,

实现状态逻辑的复用。

useMousePosition

useWindowSize

Custom-Hooks 中使用其他 Custom-Hooks

3 React-Hooks使用中的问题

Hooks FAQ

闭包陷阱

Demo地址

闭包陷阱

Class Component 会不会有同样的问题呢

Class Component

Hook 的解决方案

我们需要一个类似Class中this的功能

这个时候我们可以使用一个Ref来保存可

变的变量,并对它进行读写

Class 里也存在闭包陷阱

通过闭包的方式来访问count,在

Alert时候就是render时得到的那个

数值

因此,闭包陷阱并不是 React-Hooks

自身的问题,而是React-Hooks要求

开发者对闭包需要有更深刻的理解。

setInterval or useInterval

通过观察,我们可以发现

右边的代码会有个Bug

setInterval or useInterval

虽然我们可以通过

setCount传入一个函数去

更新count,但是这么做

在一个复杂场景中可能不

适用,并不是我们最终想

要的。

setInterval or useInterval

useInterval的实现

我们的delay可以动态调整

并且传入一个负数后可以暂停我

们的定时器 Demo地址

setInterval or useInterval

这才是我们想要的版本

setInterval or useInterval

来看下我们的Hooks 版本

setInterval or useInterval

在Class-Component中我们要如何实现呢?

useInterval 实战

这个消息数量组件在中后台项目中很常见

现在我们可以使用 useInterval 去轮询接口,获取消息数量了

但是,我们只要无脑用定时器去轮询接口就可以了吗?

useInterval + useVisibility

如果我们同时打开了多个含有消息通知的页面,但当前仅有一个Tab是可见的

这个时候我们的页面不应该无脑轮询调用接口,浪费性能和资源

现在我们就需要实现一个 useVisibility 的 Custom-Hooks 来组合使用了

useVisibility的实现

useInterval + useVisibility

那现在我们只要把 2个 Custom-

Hooks 组合使用 或者 重新组合

成一个 useIntervalOnVisibile

就实现了我们想要的效果了

useInterval + useVisibility

但是,现在我们只要把 2个 Custom-Hook 重新组合成一个

useIntervalOnVisibile 就完事了吗?

假设我们轮询的间隔为 30s,当页面不可见的时候我们暂停我们

的轮询,1分钟后 我们重新回到了当前Tab,这时我们的请求应

该立即发出,而不是在30s后请求数据,这又该如何实现呢?

事情远远没有这么简单!

4 探索 React-Hooks 内部以 useState 和 useReducer 为例

如何用 useState

实现简易版的 useReducer

如何用 useReducer

实现简易版的 useState

React内部真正的调用

React-hooks 解决了什么问题

React 一直在探索如何实现分离业务逻辑代码,复用组件内的业务逻辑

Hooks 是现阶段的一个有效解决方案,既避免了 class component 的问题,又增强了 function component 的能力

Hooks 允许我们写 custom hook,使我们得到了除了组件以外的新的组合维度——状态和业务逻辑的组合

以后的 React 项目里,除了 components/ 目录以外,将增加 hooks/ 目录

Hooks 与即将到来的 React-Suspense 和 React-ConcurrentMode 的互相配合,也将释放更多的想象力,让我们拭目以待

THANK YOU

李子翔@Ctrip

Q&A

top related