React的高阶组件

125 阅读2分钟

什么是高阶函数

  • 高阶函数的维基百科定义:至少满足以下条件之一:
    • 接受一个或多个函数作为输入;
    • 输出一个函数:

高阶组件 ★★★

高阶组件(higherOrderComponent简称(HOC))是 React 中用于复用组件逻辑的一种高级技巧:是一种基于 React 的组合特性而形成的设计模式

高阶组件是参数为组件,返回值为新组件的函数。 组件是将 props 转换为 UI,而高阶组件是将组件转换为另一个新组件。其实是对新组件进行了一次拦截

import React, { PureComponent } from 'react'

function hoc(WrappedComponent) {
  // 定义 类组件进行拦截操作
  class NewWrappedComponent extends PureComponent {
    render() {
      return (
        <div>
          <WrappedComponent name="我是拦截后新增的数据" />
        </div>
      )
    }
  }
  return NewWrappedComponent
}
// 这里定义常用组件
class Son extends PureComponent {
  render() {
    const { name } = this.props
    return (
      <div>显示Son组件,我是参数props:{name}</div>
    )
  }
}
// 使用高阶函数,实际对Son组件进行拦截操作内容数据
const ComHOC = hoc(Son)
export class App extends PureComponent {
  render() {
    return (
      <div>
        {/* 默认用法 */}
        <h1><Son/></h1>
        {/* 高阶组件 */}
        <ComHOC />
      </div>
    )
  }
}

export default App

应用示例

import React, { PureComponent } from 'react'
// 高阶组件这里可以抽取出去作为Hook使用为了方便没有抽取直接观察理解
function higherOrderComponent(OldCompon){ 
  class NewCom extends PureComponent{
    constructor(props){
      super(props)
      this.state={
        info:{
          name:"林夕",
          age:18
        }
      }
    }
    render(){
      return(
        <OldCompon {...this.props} {...this.state.info}/>
      )
    }
  }
  return NewCom
}

const Header=higherOrderComponent(function(props) {
  return (
   <div>
     <h1>Header :{props.name}-{props.age}  </h1>
     <h1>主动传输 :{props.topName}  </h1>
   </div>
  )
})
export class App extends PureComponent {
  render() {
    return (
      <div>
        <Header/>
        <Header topName="我是主动传输参数"/>
      </div>
    )
  }
}
export default App

搭配Context使用

import React, { createContext, PureComponent } from 'react'
const ThemeContext = createContext()
//可以作为单独js库进行拆分
function withTheme(Com) {
  return (props) => {
    return (
      <ThemeContext.Consumer>
        {
          value => {
            return <Com {...value} {...props}></Com>
          }
        }
      </ThemeContext.Consumer>
    )
  }
}
// 子组件内容
class Comson extends PureComponent {
  render() {
    const { name, age } = this.props
    return (
      <div>
        <h1>{name}-{age}</h1>
      </div>
    )
  }
}

const Son = withTheme(Comson)
// 父组件
export class App extends PureComponent {
  render() {
    return (
      <div>
        <ThemeContext.Provider value={{ name: "林夕", age: 18 }}>
          <Son />
        </ThemeContext.Provider>
      </div>
    )
  }
}

export default App

搭配登录进行高阶组件

import React, { PureComponent } from 'react'

// 作为登录拦截操作
function loginCheck(WrappedComponent) {
  return (props) => {
    const login = localStorage.getItem("login")
    if (login) {
      return <WrappedComponent />
    } else {
      return <h1>暂未登录</h1>
    }
  }
}
// 组件使用
class SonComponent extends PureComponent {
  render() {
    return (
      <div>SonComponent</div>
    )
  }
}
// 高阶组件使用
const SonComp = loginCheck(SonComponent)

export class App extends PureComponent {
  constructor() {
    super()
    this.state = {
      isLogin: false
    }
  }
  login() {
    const { isLogin } = this.state
    const loginToken = localStorage.getItem("login")
    if (loginToken && isLogin) {
      localStorage.removeItem("login")
    } else {
      localStorage.setItem("login", true)
    }
    this.setState((state) => ({ isLogin: !state.isLogin }))
    // 如果你不想使用state而进行改变内容可以使用
    // this.forceUpdate()
  }
  render() {
    const { isLogin } = this.state
    return (
      <div>
        App
        <button onClick={e => this.login()}>{isLogin ? '退出登录' : '点击登录'}</button>
        <SonComp />
      </div>
    )
  }
}

export default App

缺点

  • HOC需要在原组件上进行包裹或者嵌套,如果大量使用HOC,将会产生非常多的嵌套,调试起来非常困难;
  • HOC可以劫持props,在不遵守约定的情况下也可能造成冲突:
    • 例如钻进传输一个名为name的属性,但是HOC可能重新定义name属性造成覆盖