孤狼的博客
基于React Context Api 和 Es6 Proxy的状态管理 - 2019-01-25

  近几个月的工作中,有遇到一些场景:基本不需要全局的状态管理,但页面级的,肯定需要在一些组件中共享,引入Redux这类状态管理库有点繁琐,直接通过props传递的话,写起来总觉得不是那么优雅。刚好项目中React版本比较新,就试了下Context Api,代码大致如下:

jsx
jsx
jsx

  以上是官方文档中给出的用法,好处在于不用借助第三方状态管理库,也不需要手动传递props,但看起来不是很灵活,其实对于Provider和Consumer这种高阶组件,我们可以借助decorators来简化写法,最后应该能到达一下这种效果:

jsx
jsx

  可以看到这里的Provider和Consumer很简洁,当然这也并非是Context中的Provider和Consumer,state状态的维护也抽离出去了,所有的这些逻辑是怎么实现的呢?先上代码:

jsx

  这里已一个查询列表为例,这样封装了之后,不管是查询、翻页或者其他操作,页面上直接从props中取出来操作就行。ProviderClass中就是常规的操作state的逻辑,可以按照个人习惯来写。

  Provider的封装也比较简单,但同时也可以很灵活,可以在前面再加个参数,比如type之类的,然后使用的时候:@Provider(type),总之,按自己的需求来写。

  看起来Consumer的实现稍微复杂点,其实做的事情很简单,就是处理@Consumer()@Consumer('name')@Consumer(['key1', 'key2'])@Consumer(val=>({name: val.name}))这几种情况,毕竟想要更灵活嘛,而且,后面还实现了一种更灵活的Consumer.

  这么写好像更复杂了啊,比之前的代码还要多,还要难以理解?但你应该也发现了,这个Context.js可以说是一个通用的,在不同的场景,只需要实现ProviderClass中状态管理这部分就行了,然后就稍微把Provider和Consumer这两部分提取出来,写个module,以后直接import直接用就好了,一直这么想,可这几个月一直没时间去实现,每次都是yy / p拷贝过来直接用。其实复制粘贴也没那么麻烦(ーー゛)。

  最近终于有时间来总结一下了,这次实现了state的分离(直接写一个普通的es6 class就行),以及多Provider的场景,而且Provider、Consumer的使用更灵活了,废话不多说,直接来看一下最后的成果:

js
jsx
jsx

  然后,没有然后了,就是这么简单。当然,既然说了要灵活,那就一定是你想怎样就怎样。

jsx

  这次真的没了, 毕竟也就一百来行代码,还要啥自行车。不过存在的一些潜在问题还是需要解决的,后续考虑加入scoop。

  至于怎么实现的,其实大部分和上面对Context的封装差不多,对于state的抽离这部分稍微要注意点,用到了es6的Proxy, 在监听到set时触发更新,另外考虑到state中值为对象的情况,需要递归Proxy。

  代码已丢到github,https://github.com/evolify/ctx-react

  也发到了npm:yarn add ctx-react

  本以为最近能闲下来玩一下golang,这篇文章还没写完就又忙起来了,算了算了,还是先搬砖吧。