You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在React中使用HOC避免切换组件的代码重复

React 高阶组件(HOC)实现状态切换逻辑复用

把重复的状态切换逻辑封装进withToggler高阶组件,它会将状态和切换方法以props形式传递给被包装的业务组件,这样两个组件就不用再写重复的构造函数和toggle方法了。

1. 实现 withToggler 高阶组件

// withToggler.js
import React, { Component } from 'react';

const withToggler = (WrappedComponent) => {
  return class extends Component {
    constructor(props) {
      super(props);
      this.state = { isToggled: false };
      this.toggle = this.toggle.bind(this);
    }

    toggle() {
      this.setState(prevState => ({ isToggled: !prevState.isToggled }));
    }

    render() {
      // 把状态、切换方法,还有原组件的其他props一并传递
      return (
        <WrappedComponent
          isToggled={this.state.isToggled}
          toggle={this.toggle}
          {...this.props}
        />
      );
    }
  };
};

export default withToggler;

2. 改造 Clickbtn 组件

删掉原本的构造函数和toggle方法,直接使用HOC传入的props完成渲染:

// Clickbtn.js
import React from 'react';
import withToggler from './withToggler';

const Clickbtn = ({ isToggled, toggle }) => (
  <button onClick={toggle}>
    {isToggled ? 'OK' : 'NOK'}
  </button>
);

// 用HOC包装组件后导出
export default withToggler(Clickbtn);

如果你的Clickbtn原本是类组件,改成这样也可以:

// 类组件版本的Clickbtn
import React, { Component } from 'react';
import withToggler from './withToggler';

class Clickbtn extends Component {
  render() {
    const { isToggled, toggle } = this.props;
    return (
      <button onClick={toggle}>
        {isToggled ? 'OK' : 'NOK'}
      </button>
    );
  }
}

export default withToggler(Clickbtn);

3. 改造 Hideshow 组件

同样去掉重复逻辑,专注于菜单的显示隐藏渲染逻辑:

// Hideshow.js
import React from 'react';
import withToggler from './withToggler';

const Hideshow = ({ isToggled, toggle }) => (
  <div>
    <button onClick={toggle}>切换菜单</button>
    {isToggled && (
      <div className="menu">
        <p>菜单选项1</p>
        <p>菜单选项2</p>
      </div>
    )}
  </div>
);

export default withToggler(Hideshow);

类组件版本:

// 类组件版本的Hideshow
import React, { Component } from 'react';
import withToggler from './withToggler';

class Hideshow extends Component {
  render() {
    const { isToggled, toggle } = this.props;
    return (
      <div>
        <button onClick={toggle}>切换菜单</button>
        {isToggled && (
          <div className="menu">
            <p>菜单选项1</p>
            <p>菜单选项2</p>
          </div>
        )}
      </div>
    );
  }
}

export default withToggler(Hideshow);

4. 使用改造后的组件

在父组件里直接引入使用即可,无需额外处理状态管理:

// App.js
import React from 'react';
import Clickbtn from './Clickbtn';
import Hideshow from './Hideshow';

function App() {
  return (
    <div>
      <Clickbtn />
      <Hideshow />
    </div>
  );
}

export default App;

额外优化:支持自定义初始状态

如果需要给不同组件设置不同的初始状态,可以给HOC添加配置参数:

// 带初始状态配置的withToggler
const withToggler = (WrappedComponent, initialState = false) => {
  return class extends Component {
    constructor(props) {
      super(props);
      this.state = { isToggled: initialState };
      this.toggle = this.toggle.bind(this);
    }

    toggle() {
      this.setState(prevState => ({ isToggled: !prevState.isToggled }));
    }

    render() {
      return (
        <WrappedComponent
          isToggled={this.state.isToggled}
          toggle={this.toggle}
          {...this.props}
        />
      );
    }
  };
};

// 使用时指定初始状态,比如让Clickbtn默认显示OK
export default withToggler(Clickbtn, true);

内容的提问来源于stack exchange,提问作者Moez Ben Rebah

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.16 07:25:20