从 custom Hooks 到 shared Hooks :hox 原理分析

图像处
• 阅读 2029
本文旨在用尽可能通俗易懂的方式讲清楚 hox 在底层是如何实现的,也因此可能在某些方面的表述不够严谨,如有偏颇,还请各位读者多多指正。

Hox 是下一代的 React 状态管理器,关于它的更多介绍可以参考这篇文章,本文假设你已经对 hox 的用法有了初步的了解。

在 hox 中,我们希望能充分发挥 React Hooks 的特性,也希望让全局状态和组件内部状态的编写体验保持一致,所以我们使用 custom Hook 的方式定义 model 的逻辑。

我们不妨先来看下一个普通的 custom Hook 是什么样的效果吧:

export function useFoo() {
  const [count, setCount] = useState(0)
  function increment() {
    setCount(count + 1)
  }
  return {
    count,
    increment,
  }
}

我们可以在组件中调用 useFoo

export function ComponentA() {
  const foo = useFoo()
  return (
    <div>
      <p>{foo.count}</p>
      <button onClick={foo.increment}>Increment</button>
    </div>
  )
}

不难发现,我们通过定义 custom Hook ,对逻辑进行了一层封装,也让组件变得更加简洁。然而,如果此时我们再创建一个 B 组件:

export function ComponentB() {
  const foo = useFoo()
  return (
    <div>
      <p>{foo.count}</p>
    </div>
  )
}

当我们点击 A 组件中的 Increment 按钮时,B 组件中的数字会跟着变化么?
答案自然是不会的,因为 useFoo 这个 custom Hook 虽然实现了逻辑的封装复用,但是却并不能让数据共享

而 hox ,就是为了解决这个问题而生。

我们不妨接着上面的例子,使用 hox 提供的 createModeluseFoo 进行一层封装:

const useFooModel = createModel(useFoo)

createModel 会创建一个 Executor 组件的实例,并在其中执行 useFoo 这个 Hook ,并把 useFoo 的执行结果保存起来。最后,它会返回一个新的 Hook: useFooModel 。乍一看, createModel 和 HOC (高阶组件)甚至有几分神似。

从 custom Hooks 到 shared Hooks :hox 原理分析

不同于 useFoo ,在调用 useFooModel 时,我们并不是真的执行了 useFoo 这个 custom Hook ,而是向 Executor 组件进行数据的订阅。也就是说,如果我们在多个组件中都调用了 useFooModel ,那它们所拿到的数据实际上是同一份,更准确的说,它们拿到的那份数据,就是存在 Executor 中的那份 state

从 custom Hooks 到 shared Hooks :hox 原理分析

通过这种方式,我们让 custom Hook 可以做到数据的共享,这也是 createModel 之所以叫做 createModel 的原因:通过它,我们把一个 custom Hook 变成了一个全局的 model 。

现在,我们再来更新一下刚才的例子:

export function ComponentA() {
  const foo = useFooModel() // 这里从 useFoo 变成了 useFooModel
  return (
    <div>
      <p>{foo.count}</p>
      <button onClick={foo.increment}>Increment</button>
    </div>
  )
}

export function ComponentB() {
  const foo = useFooModel() // 这里从 useFoo 变成了 useFooModel
  return (
    <div>
      <p>{foo.count}</p>
    </div>
  )
}

现在,A B 两个组件都获取到了 Executor 中的那份数据,并且订阅了它未来的更新。因此当我们点击组件 A 的 Increment 按钮时,我们实际上是触发了 Executor 组件中的一个 setState ,然后 Executor 组件进行重渲染,通知它的订阅者们。A 组件和 B 组件收到了更新通知和新的数据,也会跟着重新进行渲染。最终我们可以看到,A B 两个组件显示的数字都变成了 1

如果你希望对 hox 有更多的了解的话,不妨在 GitHub 上阅读它的源码,或是亲自体验一下~

点赞
收藏
评论区
推荐文章
blmius blmius
4年前
MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1
文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s
Oracle 分组与拼接字符串同时使用
SELECTT.,ROWNUMIDFROM(SELECTT.EMPLID,T.NAME,T.BU,T.REALDEPART,T.FORMATDATE,SUM(T.S0)S0,MAX(UPDATETIME)CREATETIME,LISTAGG(TOCHAR(
Wesley13 Wesley13
4年前
MySQL部分从库上面因为大量的临时表tmp_table造成慢查询
背景描述Time:20190124T00:08:14.70572408:00User@Host:@Id:Schema:sentrymetaLast_errno:0Killed:0Query_time:0.315758Lock_
皕杰报表之UUID
​在我们用皕杰报表工具设计填报报表时,如何在新增行里自动增加id呢?能新增整数排序id吗?目前可以在新增行里自动增加id,但只能用uuid函数增加UUID编码,不能新增整数排序id。uuid函数说明:获取一个UUID,可以在填报表中用来创建数据ID语法:uuid()或uuid(sep)参数说明:sep布尔值,生成的uuid中是否包含分隔符'',缺省为
Wesley13 Wesley13
4年前
FLV文件格式
1.        FLV文件对齐方式FLV文件以大端对齐方式存放多字节整型。如存放数字无符号16位的数字300(0x012C),那么在FLV文件中存放的顺序是:|0x01|0x2C|。如果是无符号32位数字300(0x0000012C),那么在FLV文件中的存放顺序是:|0x00|0x00|0x00|0x01|0x2C。2.  
Stella981 Stella981
4年前
SpringBoot整合Redis乱码原因及解决方案
问题描述:springboot使用springdataredis存储数据时乱码rediskey/value出现\\xAC\\xED\\x00\\x05t\\x00\\x05问题分析:查看RedisTemplate类!(https://oscimg.oschina.net/oscnet/0a85565fa
Wesley13 Wesley13
4年前
mysql设置时区
mysql设置时区mysql\_query("SETtime\_zone'8:00'")ordie('时区设置失败,请联系管理员!');中国在东8区所以加8方法二:selectcount(user\_id)asdevice,CONVERT\_TZ(FROM\_UNIXTIME(reg\_time),'08:00','0
Wesley13 Wesley13
4年前
PHP创建多级树型结构
<!lang:php<?php$areaarray(array('id'1,'pid'0,'name''中国'),array('id'5,'pid'0,'name''美国'),array('id'2,'pid'1,'name''吉林'),array('id'4,'pid'2,'n
Easter79 Easter79
4年前
SpringBoot整合Redis乱码原因及解决方案
问题描述:springboot使用springdataredis存储数据时乱码rediskey/value出现\\xAC\\xED\\x00\\x05t\\x00\\x05问题分析:查看RedisTemplate类!(https://oscimg.oschina.net/oscnet/0a85565fa
Wesley13 Wesley13
4年前
Java日期时间API系列36
  十二时辰,古代劳动人民把一昼夜划分成十二个时段,每一个时段叫一个时辰。二十四小时和十二时辰对照表:时辰时间24时制子时深夜11:00凌晨01:0023:0001:00丑时上午01:00上午03:0001:0003:00寅时上午03:00上午0
Python进阶者 Python进阶者
2年前
Excel中这日期老是出来00:00:00,怎么用Pandas把这个去除
大家好,我是皮皮。一、前言前几天在Python白银交流群【上海新年人】问了一个Pandas数据筛选的问题。问题如下:这日期老是出来00:00:00,怎么把这个去除。二、实现过程后来【论草莓如何成为冻干莓】给了一个思路和代码如下:pd.toexcel之前把这