react基础(十二)— 高阶组件的使用

914 阅读3分钟

一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第12天,点击查看活动详情

前言

大家好呀,我是L同学。在上篇文章中react基础(十一),我们学习了react中的事件总线和ref的使用和类型。接下来,我们将学习到react中高阶组件的知识点。

什么是高阶组件

高阶组件(Higher-Order Component, HOC)是什么呢?在学习高阶组件之前,我们听说过高阶函数,它们非常相似,所以我们先来学习下什么是高阶函数。

高阶函数至少满足以下条件之一:

  • 接收一个或多个函数作为输入;
  • 输出一个函数

那么什么是高阶组件呢?官方定义为高阶组件是参数为组件,返回值为新组件的函数

我们来解读下。第一,高阶组件是一个函数,本身不是一个组件。第二,这个函数的参数是一个组件,返回值也是一个组件。

高阶组件的使用

我们通过代码来看下高阶组件。enhanceComponent是一个高阶组件,接收的参数是一个组件,返回值是一个组件。

function enhanceComponent(WrappedComponent) {
  class NewComponent extends PureComponent {
    render() {
      return <WrappedComponent/>
    }
  }
  return NewComponent
}

我们先定义一个App组件,然后作为参数传入高阶组件。

class App extends PureComponent {
  render() {
    return (
      <div>
        App
      </div>
    )
  }
}

调用高阶组件,并且传入App组件。

const EnhanceComponent = enhanceComponent(App)

然后通过export default进行导出。

export default EnhanceComponent

我们可以看到页面可以正常显示。并且在调试工具这儿可以看到类名

image.png 在ES中,类表达式的类名是可以省略的。所以我们也可以这样写。

function enhanceComponent(WrappedComponent) {
  return class extends PureComponent {
    render() {
      return <WrappedComponent/>
    }
  } 
}

我们可以看到此时调试工具这儿的类名变成了匿名。

image.png 为了方面调试,我们可以通过disPlayName来修改组件名称。组件的名称都可以通过displayName来修改。

function enhanceComponent(WrappedComponent) {
  class NewComponent extends PureComponent {
    render() {
      return <WrappedComponent/>
    }
  }
  NewComponent.displayName = 'haha'
  return NewComponent
}

此时我们看到调试工具的组件名称变为了haha。

image.png 在开发中,我们会通过组件传递数据。现在我们往App组件中传递name,希望App组件能接受到name,并进行渲染。

ReactDOM.render(<App name='haha'/>, document.getElementById('root'))

在App组件中通过props进行接收。

class App extends PureComponent {
  render() {
    return (
      <div>
        App: {this.props.name}
      </div>
    )
  }
}

但是此时,页面上没有渲染name数据,因为App组件接收到的是undefined,undefined在页面中不显示。

image.png App组件不能渲染这是因为 <App name='haha'/> 这个组件本质上NewComponent,那么传递过来的name属性本质上是传给了NewComponent。因此我们可以通过之前讲过的...语法来获取到传递过来的name属性。

<WrappedComponent {...this.props}/>

此时我们可以看到页面正常渲染了name属性。

image.png 刚刚我们在高阶组件中返回的是类组件。除了类组件,高阶组件还可以返回函数组件。

function enhanceComponent2(WrappedComponent) {
  function NewComponent(props) {
    return <WrappedComponent {...props}/> 
  }
  NewComponent.displayName = 'xixi'
  return NewComponent
}

const EnhanceComponent = enhanceComponent2(App)

需要注意的是,高阶组件并不是react API的一部分,它是基于react的组合特性而形成的设计模式。高阶组件在一些react第三方库中非常常见。比如redux中的connect,react-router中的withRouter。我们后续进行讲解。