react中的高阶组件

什么是高阶函数?

高阶函数的维基百科定义:至少满足以下条件之一:

  1. 接受一个或多个函数作为输入;
  2. 输出一个函数;
    JavaScript中比较常见的filter、map、reduce都是高阶函数;

什么是高阶组件呢?

1. 高阶组件的英文是 Higher-Order Components,简称为 HOC; 
2. 官方的定义:高阶组件是参数为组件,返回值为新组件的函数;
3. 组件是将 props 转换为 UI,而高阶组件是将组件转换为另一个组件;
4.高阶组件并不是React API的一部分,它是基于React的 组合特性而形成的设计模式;
5. 高阶组件在一些React第三方库中非常常见: 
    比如redux中的connect;
    比如react-router中的withRouter;

基本使用如下:
在这里插入图片描述

应用场景

场景一: props增强

  • 不修改原组件的情况下,添加新的props:
import React, { PureComponent } from 'react';

// 定义一个高阶组件
function enhanceRegionProps(WrappedComponent) {
  return (props) => {
    // 所有组件公共的region
    return <WrappedComponent {...props} region="中国" />;
  };
}

class Home extends PureComponent {
  render() {
    return (
      <h2>
        Home:
        {`昵称: ${this.props.nickname} 等级: ${this.props.level} 区域: ${this.props.region}`}
      </h2>
    );
  }
}

class About extends PureComponent {
  render() {
    return (
      <h2>
        About:
        <ul>
          <li>昵称:{this.props.nickname}</li>
          <li>等级:{this.props.level}</li>
          <li>区域:{this.props.region}</li>
        </ul>
      </h2>
    );
  }
}

const EnhanceHome = enhanceRegionProps(Home);
const EnhanceAbout = enhanceRegionProps(About);

class App extends PureComponent {
  render() {
    return (
      <div>
        App
        <EnhanceHome nickname="tsw" level={90} />
        <EnhanceAbout nickname="wh" level={99} />
      </div>
    );
  }
}

export default App;
  • 利用高阶组件来共享context:
import React, { PureComponent, createContext } from 'react';

// 3. 定义一个高阶组件,接收context共享的数据
function withUser(WrappedComponent) {
  return (props) => {
    return (
      <UserContext.Consumer>
        {(user) => {
          // 4. 传递到每个组件中:
          return <WrappedComponent {...props} {...user} />;
        }}
      </UserContext.Consumer>
    );
  };
}

// 1. 创建Context
const UserContext = createContext({
  nickname: '默认',
  level: -1,
  区域: '中国',
});

class Home extends PureComponent {
  render() {
    return (
      <h2>
        Home:{' '}
        {`昵称: ${this.props.nickname} 等级: ${this.props.level} 区域: ${this.props.region}`}
      </h2>
    );
  }
}

class Detail extends PureComponent {
  render() {
    return (
      <ul>
        <li>{this.props.nickname}</li>
        <li>{this.props.level}</li>
        <li>{this.props.region}</li>
      </ul>
    );
  }
}
// 5. 高阶组件使用:
const UserHome = withUser(Home);
const UserDetail = withUser(Detail);

class App extends PureComponent {
  render() {
    return (
      <div>
        App
        {/* 2.context 共享数据 */}
        <UserContext.Provider
          value={{ nickname: 'why', level: 90, region: '中国' }}
        >
          <UserHome />
          <UserDetail />
        </UserContext.Provider>
      </div>
    );
  }
}

export default App;

场景二: 渲染判断鉴权

在开发中,我们可能遇到这样的场景:
某些页面是必须用户登录成功才能进行进入;
如果用户没有登录成功,那么直接跳转到登录页面;

// 高阶组件:
function withAuth(WrappedComponent) {
  const NewCpn = props => {
    const {isLogin} = props;
    if (isLogin) { // 已登录- 展示正常页面组件:
      return <WrappedComponent {...props}/>
    } else { // 未登录-展示登录页面组件:
      return <LoginPage/>
    }
  }
 // 重新给组件命名:
  NewCpn.displayName = "AuthCpn"

  return NewCpn;
}

场景三: 生命周期劫持

开发中有时会遇到,多个组件页面需要记录渲染完成需要的时间;就可以通过高阶组件来抽离公共的功能; Vue中可以通过Mixin实现;

function withRenderTime(WrappedComponent) {
  return class extends PureComponent {
    // 即将渲染获取一个时间 beginTime
    UNSAFE_componentWillMount() {
      this.beginTime = Date.now();
    }

    // 渲染完成再获取一个时间 endTime
    componentDidMount() {
      this.endTime = Date.now();
      const interval = this.endTime - this.beginTime;
      console.log(`${WrappedComponent.name}渲染时间: ${interval}`)
    }

    render() {
      return <WrappedComponent {...this.props}/>
    }
  }
}

高阶函数的意义

可以发现利用高阶组件可以针对某些React代码进行更加优雅的处理。
其实早期的React有提供组件之间的一种复用方式是mixin,目前已经不再建议使用

  1. Mixin 可能会相互依赖,相互耦合,不利于代码维护;
  2. 不同的Mixin中的方法可能会相互冲突;
  3. Mixin非常多时,组件是可以感知到的,甚至还要为其做相关处理,这样会给代码造成滚雪球式的复杂性;
  4. 当然,HOC也有自己的一些缺陷:
    4.1 HOC需要在原组件上进行包裹或者嵌套,如果大量使用HOC,将会产生非常多的嵌套,这让调试变得非常困难;
    4.2 HOC可以劫持props,在不遵守约定的情况下也可能造成冲突;

Hooks的出现,是开创性的,它解决了很多React之前的存在的问题!敬请期待Hooks~

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值