Building HOCs with Recompose

什么是高阶组件?

高阶组件只是一个函数,只不过它返回的是用来渲染 React 组件的函数。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
import { Component } from 'React';

export function enhancer() {
return (BaseComponent) => {
return class extends Component {
constructor() {
this.state = { visible: false };
}
componentDidMount() {
this.setState({ visible: true });
}
render() {
return <BaseComponent {...this.props} {...this.state} />;
}
}
};
}
1
2
3
4
5
6
// 展示型组件
function Sample({ visible }) {
return visible ? <div> I am Visible </div> : <div> I am not Visible </div>
}

export default enhance()(Sample);

高阶组件的用途:

  • 可以给其他的展示型组件进行相同的代码复用;
  • 简化可读性较差的臃肿的组件;
  • 可以控制传入组件的渲染;
  • 可以给任何组件增加 state,这意味着你不再需要依赖 Redux 来托管所有 state
  • 操作你传给展示型组件的 props(map,reduce 等任何你喜欢的方法)。

高阶组件所遇问题

高阶组件在使用过程中遇到了几个问题。

  • 为简单的场景不断地编写简单地高阶组件就很无聊,
  • 没有将多个高阶组件进行合成的方法,也无法避免开发出冗余的高阶组件

我们真正需要的解决方案是这样的:

  • 强制模式
  • 易于组合
  • 易于使用

Recompose是什么

Recompose 是一个为函数式组件高阶组件开发的 React 工具库。可以把它当做 React 的 Lodash

快速入门

假如我们有这样一个组件约束:

  • 需要 state 来控制可见性;
  • 需要将改变可见性的函数放到我们的组件中;
  • 需要在组件中添加一些 props。

步骤 1 — 编写展示型组件

1
2
3
4
5
6
7
8
9
10
export default function Presentation({ title, message, toggleVisibility, isVisible }) {
return (
<div>
<h1>{title}</h1>
{isVisible ? <p>I'm visible</p> : <p> Not Visible </p>}
<p>{message}</p>
<button onClick={toggleVisibility}> Click me! </button>
</div>
);
}

步骤 2 — 编写容器

通常会把一些 Recompose 的增强型组件合成在一起,所以这个步骤是建立你的 compose:

  • 什么是 Recompose 中的 compose?它相当于 Lodash 中的 flowRight 函数。我们可以使用 compose 来将多个高阶组件转化为一个高阶组件。
1
2
3
4
5
6
7
8
9
10
import { compose } from 'recompose';

export default compose(
/***********************************
*
* 我们将把增强型组件放在这里
*
***********************************/
)(Presentation);

步骤 3 — 正确获取 state

在 Recompose 中,我们可以使用 withState 这个高阶组件来设置组件内的 state,并且使用 withHandlers 高阶组件来设置组件的事件处理函数。

1
2
3
4
5
6
7
8
9
10
11
12
import { compose, withState, withHandlers } from 'recompose';

export default compose(
withState('isVisible', 'toggleVis', false),
withHandlers({
toggleVisibility: ({ toggleVis, isVisible }) => {
return (event) => {
return toggleVis(!isVisible);
};
},
})
)(Presentation);

这里我们设置了一个 isVisiblestate,一个控制可见性的方法 toggleVis,和一个初始值 false。

withHandlers 创建了一个高阶组件,它接受一系列 props 并返回一个处理函数,在这个例子中是切换可见性 state 的函数。toggleVisibility 这个函数将作为 Presentation 组件的一个 prop

步骤 4 — 添加 props

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
import { compose, withState, withHandlers, withProps } from 'recompose';

export default compose(
withState('isVisible', 'toggleVis', false),
withHandlers({
toggleVisibility: ({ toggleVis, isVisible }) => {
return (event) => {
return toggleVis(!isVisible);
};
},
}),
withProps(({ isVisible }) => {
return {
title: isVisible ? 'This is the visible title' : 'This is the default title',
message: isVisible ? 'Hello I am Visible' : 'I am not visible yet, click the button!',
};
})
)(Presentation);

这个模式最酷的地方在于我们现在就可以操作组件的 props 了,在这里,通过操作控制可见性的 state,我们可以展示不同的 title 和 message。依我看,这个增强型组件远比原来全写在 render 函数中的方式简洁。

https://juejin.im/post/5c484a43e51d452ec621b6a9