Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

React Custom Hooks 最佳实践 #31

Open
brickspert opened this issue Oct 13, 2019 · 7 comments
Open

React Custom Hooks 最佳实践 #31

brickspert opened this issue Oct 13, 2019 · 7 comments

Comments

@brickspert
Copy link
Owner

brickspert commented Oct 13, 2019

组件

组件是 UI + 逻辑的复用,但逻辑复用能力等于 0。

一个 React 项目,是由无数个大大小小的组件组合而成的。在 React 的世界中,组件是一等公民。而我们平时拆分组件的依据无非是:尽量的复用代码。

组件是 UI + 逻辑的复用,你不能将 UI 和逻辑拆开。比如 Antd 的 Cascader 级联选择 组件,内置了样式和级联选择的逻辑,用户使用的时候相当于一个黑盒,只管用就行了。但是有一个很现实的问题,当该组件的样式不能满足我们需求的时候,我们需要从 0 重新实现一个组件,重写 UI + 逻辑,哪怕逻辑真的一模一样。组件的逻辑复用能力等于 0。我可以想到一个可怕的事实,社区上的同类组件,大部分的逻辑都是可以复用的,只是在样式上有差异,但逻辑共享在社区上并没有很流行。

HOC 与 Render Props

HOC 与 Render Props 可以把逻辑抽出来复用,但并没有让逻辑复用流行起来。

当然,我上面说的不能复用有点夸张,React 提供了 HOC 与 Render Props 两种方式来解决逻辑复用的问题。比如下面的监听鼠标位置的逻辑,我们就可以通过 Render Props 来复用。

<Mouse>
  (position)=> <OurComponent />
</Mouse>

同类逻辑包括监听 window size,监听 scroll 位置等等。但是我们一般很少用 render props 来封装逻辑,更少去和其它项目去共享逻辑。为什么呢?想想多个逻辑复用会怎么样,你就知道多可怕了。

<WindowSize>
  (size)=> (
        <Mouse>
        (position)=> <OurComponent size={size} mouse={position}/>
    </Mouse>
    )
</WindowSize> 

嵌套地狱的代码是我们不能忍受的,同时 HOC 也存在类似的问题,这可能是导致逻辑复用不能流行起来的一个重要原因。

React Hooks

React Hooks 很好的解决了逻辑复用的问题,同时社区中诞生了一批比较好的 React Hooks 库。

React Hooks 是今年 React 的一个重磅炸弹,在社区引起了激烈的回响。随着 Hooks 的诞生,我们可以通过 Custom Hooks 很方便的封装逻辑,逻辑共享也成为了潮流。比如上面的例子,我们就可以通过 react-use 很方便的实现。

import {useMouse, useWindowSize, useScroll} from 'react-use'

function Demo(){
  const mousePosition = useMouse();
  const windowSize = useWindowSize();
}

react-use 是社区中比较优秀的 Hooks 库,封装了很多常用的基础逻辑,在日常开发中必不可少。但是只用 react-use 就够了吗?显然不是。react-use 中的 Hooks 粒度比较小,类似于工具库。而在中台产品中,有很多特定的场景逻辑,需要多个 Hooks 进行组合,或者定制特定的逻辑。基于此,我们创建了 @umijs/hooks ,定位为为中台场景服务的 Hooks 库。

@umijs/hooks

@umijs/hooks 是面向中台应用场景的 Hooks 库,封装了中台常见场景的逻辑,让中台开发变得超级简单。@umijs/hooks 已经在蚂蚁金服多个产品中落地,口碑很好,提效明显。当然,你可能不信,口说无凭,那就用例子来说话。

useAntdTable

中台开发中,table 页面应该算最多的一个了,我们一般会使用 Antd 的 Table 组件来搭建,但是其中还是有很多逻辑,我们是无法避免的。

  1. 分页管理
  2. pageSize管理
  3. 分页变化,pageSize 变化时重新进行异步请求
  4. 筛选条件变化时,重置分页,并重新请求数据
  5. 异步请求的 loading 处理
  6. 异步请求的竞态处理
  7. 组件卸载时丢弃进行中的异步请求(很多人通常不处理,在某些情况会报警告)

上面的逻辑,我们在几乎所有的 table 页是必须要处理的,想想都可怕。useAntdTable 至少封装了上面 7 个逻辑,列表页开发从未变得如此简单

const { table } = useAntdTable(asyncFn);
const columns = [];
return (
  <Table columns={columns} rowKey="id" {...table} />
)

useSearch

2019-10-13 16 40 37

常见的异步搜索场景,我们一般要集成:

  1. 防抖
  2. 异步请求的 loading 处理
  3. 异步请求的请求时序控制
  4. 组件卸载时取消防抖及异步请求等逻辑

现在一切变得如此简单:

const { data, loading, onChange } = useSearch(asyncFn);

<Select
  onSearch={onChange}
  loading={loading}
>
  {data.map((item)=><Option />)}
</Select>

更多的 Custom Hooks

当然,我们还有更多极大提效的 CustomHooks,你能想象不用写一行逻辑,就能实现异步 loadmore 功能吗?

2019-10-13 16 45 38

你能想象不用写一行逻辑,就能实现动态增删,排序的表单吗?

2019-10-13 16 50 18

各种常见场景,通通不用写逻辑,通通不用写逻辑。

写在最后

umi hooks 让中台开发变得如此简单,我能想象,不久的将来,中台开发可以不用写一行逻辑,这也是我们为之奋斗的目标。

同时,我也知道,大家平时工作中也积累了很多常用的 Hooks,我们非常希望大家能参与进来,共建 umi hooks,无论对我们,还是用户,都是最好的福音。

❤️感谢大家

关注公众号「前端技术砖家」,拉你进交流群,大家一起共同交流和进步。

image

@moneynoend
Copy link

antd 重度用户,也在思考 antd 的组件逻辑的封装,先试用一下 umi hooks

@songchengen
Copy link

对antd的版本有要求吧

@brickspert
Copy link
Owner Author

对antd的版本有要求吧

只有 useAntdTable,这一个是和 antd 耦合的,其他的都和 antd 没关系。 并且对 antd 的版本没要求的。

@ttys026
Copy link

ttys026 commented Oct 16, 2019

useAntdTable 4.0 新的 Table 和 Form 的用法我们这边也看过了,现在内部项目里已经有
antd4.0 Table + useAntdTableantd4.0 Form + useDynamicList 落地的场景了。作为纯粹逻辑的封装,对 antd 版本的依赖性不大,后面如果有使用差异我们也会第一时间补充上文档。

@peterpanBest
Copy link

大哥有没有微信交流群呀

@fireairforce
Copy link

期待umi的发展

@KingJeason
Copy link

对antd的版本有要求吧

只有 useAntdTable,这一个是和 antd 耦合的,其他的都和 antd 没关系。 并且对 antd 的版本没要求的。

其实我理解的是,hooks和任何ui层面上的东西都没有耦合,因为hooks暴露的是能力(接口),任何ui组件只要实现了这个接口就可以使用.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

7 participants