最近,项目中在使用react-google-maps
,研究期间发现了Recompose
这个库,一个看起来非常函数式
的库,第一眼看上去感觉很不好,但是也引起了我研究的兴趣。
项目背景
-
项目中一直致力于找到好的pattern将业务逻辑和组件进行分离,因此follow了redux的模式,将一个组件分成两个部分
adapter
和view
。adapter只负责数据的处理,view只负责拿到数据展示。因此基本呈现这样数据结构const Component = props => <View {...adapter(props)} />
看起来已经很棒了,但是我有了一些问题
- 需要使用到生命周期的组件component岂不是又要掺杂一堆业务逻辑?
- 所有组件都是函数,那么某一个组件的数据源变化,然后组件重新创建,这个组件的子组件,孙子组件,孙子的子组件。。。都要重新创建,那么这样性能问题该如何解决呢?
- 为了将数据和
view
组件绑定,我们创建了一个special
的组件,这个组件的功能只包含compose
。那么这么common
的行为为什么不提出一个function,既然想要每一个组件都分离逻辑和视图那么专门提取一个function(HOC)岂不更好?为什么不学学redux的做法呢?
Recompose出现
Recompose的出现,感觉我的所有问题都有了解答。
Recompose是一个什么样的库?
按照他的文档描述: 他就是React
的lodash
,帮助你非常简单的将业务逻辑和组件分离。
概览
: Recompose库中全部都是function,库里的function大多都是将你的组件提升为HOC
。-
思路
:-
抽象划分
:将一个React Component
中包含的common feature
进行粗粒度的划分,比如:props、state、event都可以被划分成组件中一小部分的功能。将每一个部分都抽象出一个common function。 -
组合
:既然组件包含的功能都被划分成每个小的function,那么就必然需要将这些功能组合在一起构成一个新的组件。
此时,不仅仅是组件的数据部分和视图可以分离,甚至还可以将数据部分继续划分成耕细粒度的模块,最后compose起立成为一个高阶组件。
-
Recompose的启发
说到数据和视图的分离,首先想到的是connect,之前觉得redux
的connect
函数是一个很难让人理解的东西
const mapStateToProps = state => ({data: state.data})
const mapDispatchToProps = dispatch => ({
handleClick: (data) => dispatch(aciton(data))
})
export default connect(mapStateToProps,mapDispatchToProps)(View);
一个connect
函数接受两个函数作为参数返回一个函数而这个函数接受了组件作为参数又返回了一个组件。其实现在想想是很好的处理方式。
connect解读
connect函数接受function作为参数,利用了柯里化实现,返回了一个高阶组件,在用的过程中一直不能理解的点有两个:
- 为什么要使用柯里化,为什么不是将所有参数收集完毕之后返回组件呢?
- 为什么要传入函数(mapStateToProps以及mapDispatchToProps)而不是数据呢?
看完源码之后有了一些理解:
我认为在这里使用柯里化原因:
使用柯里化的优点:
- 避免了给一个函数传入大量的参数
- 降低耦合度和代码冗余,便于复用
- 可以有效地将函数的功能分离,这个函数应该是做了两件事情:整合数据,创建新的组件并绑定数据。看上去connect就像函数整合数据返回的函数绑定数据。看上去组件和视图分离了
- 其实
connect(mapStateToProps,mapDispatchToProps)
函数可以被赋值给一个变量,利用函数的闭包,就好像准备好的数据可以随时的绑定给不同的组件。提升复用性能 - 这样做对于最后返回的HOC更加好理解,如果所有的参数一股脑传入,返回了一个组件,似乎不是很HOC
我认为在这里connect接收两个函数做参数的原因:
-
更加符合函数式的思想:
其实我们所理解的整合数据函数其实抽象一下就是这样:
那么继续follow这个思路,为了保证组件的common,那么如何reduce也由用户传入那函数就更加通用了。
Recompose解决痛点
-
提供各种函数直接整合数据然后直接返回HOC,直接剥离数据和组件,世界都变得简单了
const mapOwnPropsToProps = props => ({ key1: props.key1 }) const View = props => ( <div> show props {props.toJson()} <div> ) export default withProps(mapOwnPropsToProps)(View)
提供
pure以及shouldUpdate
这种简单函数,代替React.PureComponent
解决无状态组件的性能问题(虽然原理都是利用shouldComponentUpdate
方法但是看上去简单一些并且都是函数的写法)对于那些必须使用生命周期的复杂组件,提供了
lifecycle
将逻辑和组件分离提供
compose
函数将分离的组件功能组合在一起形成一个强大的HOC
。。。。
优点超多,由于这个库中文的文档比较少,所以接下来我会开始写一写recompose各种函数的使用方法