如何在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
相关产品推荐
相关产品推荐

