如果我们在高阶组件对原组件进行了修改,例如下面的代码:
- InputComponent.prototype.componentWillReceiveProps = function(nextProps) { ... }
这样就破坏了我们对高阶组件的约定,同时也改变了使用高阶组件的初衷:我们使用高阶组件是为了增强而非改变原组件。
约定-透传不相关的props
使用高阶组件,我们可以代理所有的props,但往往特定的HOC只会用到其中的一个或几个props。我们需要把其他不相关的props透传给原组件,如下面的代码:
- function visible(WrappedComponent) {
- return class extends Component {
- render() {
- const { visible, ...props } = this.props;
- if (visible === false) return null;
- return <WrappedComponent {...props} />;
- }
- }
- }
我们只使用visible属性来控制组件的显示可隐藏,把其他props透传下去。
约定-displayName
在使用React Developer Tools进行调试时,如果我们使用了HOC,调试界面可能变得非常难以阅读,如下面的代码:
- @visible
- class Show extends Component {
- render() {
- return <h1>我是一个标签</h1>
- }
- }
- @visible
- class Title extends Component {
- render() {
- return <h1>我是一个标题</h1>
- }
- }
为了方便调试,我们可以手动为HOC指定一个displayName,官方推荐使用HOCName(WrappedComponentName):
- static displayName = `Visible(${WrappedComponent.displayName})`
这个约定帮助确保高阶组件最大程度的灵活性和可重用性。
使用HOC的动机
回顾下上文提到的 Mixin 带来的风险:
- Mixin 可能会相互依赖,相互耦合,不利于代码维护
- 不同的 Mixin 中的方法可能会相互冲突
- Mixin非常多时,组件是可以感知到的,甚至还要为其做相关处理,这样会给代码造成滚雪球式的复杂性
而HOC的出现可以解决这些问题:
- 高阶组件就是一个没有副作用的纯函数,各个高阶组件不会互相依赖耦合
- 高阶组件也有可能造成冲突,但我们可以在遵守约定的情况下避免这些行为
- 高阶组件并不关心数据使用的方式和原因,而被包裹的组件也不关心数据来自何处。高阶组件的增加不会为原组件增加负担
HOC的缺陷
- HOC需要在原组件上进行包裹或者嵌套,如果大量使用HOC,将会产生非常多的嵌套,这让调试变得非常困难。
- HOC可以劫持props,在不遵守约定的情况下也可能造成冲突。
Hooks
Hooks是React v16.7.0-alpha中加入的新特性。它可以让你在class以外使用state和其他React特性。
使用Hooks,你可以在将含有state的逻辑从组件中抽象出来,这将可以让这些逻辑容易被测试。同时,Hooks可以帮助你在不重写组件结构的情况下复用这些逻辑。所以,它也可以作为一种实现状态逻辑复用的方案。
阅读下面的章节使用Hook的动机你可以发现,它可以同时解决Mixin和HOC带来的问题。
官方提供的Hooks
State Hook
我们要使用class组件实现一个计数器功能,我们可能会这样写:
- export default class Count extends Component {
- constructor(props) {
- super(props);
- this.state = { count: 0 }
- }
- render() {
- return (
- <div>
- <p>You clicked {this.state.count} times</p>
- <button onClick={() => { this.setState({ count: this.state.count + 1 }) }}>
- Click me
- </button>
- </div>
- )
- }
- }
(编辑:ASP站长网)
|