根据reactJs官方文档的定义,HOC如下:
简要来讲的话,是一种重复利用组件逻辑的技术,接受一个组件,并且返回一个组件。
就上上面的例子一样,会接受WrappedComponent然后返回enhancedComponent.下面举例子来讲解。
1.创建一个按钮组件,并且监听点击次数
import React, { Component, useState, useEffect } from "react";
class ClickCounter extends Component {
constructor() {
super();
this.state = {
count: 0
};
this.incrementCount = this.incrementCount.bind(this);
}
incrementCount() {
this.setState(preveState => {
return {
count: preveState.count + 1
};
});
}
render() {
let { count } = this.state;
return (
<div>
<button onClick={this.incrementCount}>Clicked {count} times</button>
</div>
);
}
}
export default ClickCounter;
以上按钮组件我们创建了按钮组件并且监听了点击事件,然后增加了被点击的次数.
后来我们又接到了一个需求,是要做一个监听hover次数的组件。
创建一个监听Hover次数的组件
我们很快做出来了,其实我们做的过程中只是改了事件,其余的从ClickCounter这里复制粘贴了过来。
class HoverCounter extends Component {
constructor() {
super();
this.state = {
count: 0
};
this.incrementCount = this.incrementCount.bind(this);
}
incrementCount() {
this.setState(preveState => {
return {
count: preveState.count + 1
};
});
}
render() {
let { count } = this.state;
return (
<div>
<h2 onMouseOver={this.incrementCount}>Hovered {count} times</h2>
</div>
);
}
}
然后我们做完了以后,又来了一个需求,说要写一个监听input有多少次keypressed.这个时候我们想到的第一个办法,就复制粘贴上面写的两个组件的方法,改一改事件监听函数,但我们聪明起来了,我们想到写一个父组件,然后把count和incrementCount方法通过props的方式传下来到ClickCounter,HoverCounter组件.比如一下:
这样可以解决问题,在我们这个场景可以解决问题,但如果是一下情况就不太行了 。
把逻辑代码移到最上层的组件,不是一个好的解决方式。这个时候HOC闪亮登场了,它的作用就是在组件间分享重用的逻辑代码,接受一个组件,并且返回一个增强的组件。
我们定义一个WithCounter组件,作为HOC
import React, { Component, useState, useEffect } from "react";
const UpdatedComponent = OriginalComponent => {
class NewComponent extends Component {
render() {
return <OriginalComponent name="Abdulla" />;
}
}
return NewComponent;
};
export default UpdatedComponent;
可以看到我们实现了一个组件,这个组件接受名字叫originalComponent的组件,然后返回newComponent组件。
我们在这里为了演示在originalComponent那里传了一个props,为name=“Abdulla”。
下面来看ClickCounter,HoverCounter组件有了什么变化.
我们可以看到两处有了变化,import和export那里有了变化。然后可以看到我们通过this.props.name来使用了刚才传进来的props.
在HoverCounter组件也类似,可以看到起了作用.
把count和incrementCount逻辑放到HOC组件里。
1.)我们首先把在ClickCounter和HoverCounter里的count和incrementCount逻辑移出去。
2.)在WithCounter(HOC组件)里写count和incrementCount逻辑,然后通过props传出去,就像我们传name一样。
3.)然后在ClickCounter和HoverCounter组件里使用这个props.
最后展示一下这3个组件的代码
ClickCounter组件:
import React, { Component, useState, useEffect } from "react";
import UpdatedComponent from "./WithCounter";
class ClickCounter extends Component {
constructor() {
super();
// this.state = {
// count: 0
// };
// this.incrementCount = this.incrementCount.bind(this);
}
// incrementCount() {
// this.setState(preveState => {
// return {
// count: preveState.count + 1
// };
// });
// }
render() {
// let { count } = this.state;
return (
<div>
<button onClick={this.props.incrementCount}>
{this.props.name} Clicked {this.props.count} times
</button>
</div>
);
}
}
export default UpdatedComponent(ClickCounter);
没有删掉count和incrementCount逻辑,只是注释了,为了展示的更好,显示HOC组件的优越性。
HoverCounter组件如下:
import React, { Component, useState, useEffect } from "react";
import UpdatedComponent from "./WithCounter";
class HoverCounter extends Component {
constructor() {
super();
// this.state = {
// count: 0
// };
// this.incrementCount = this.incrementCount.bind(this);
}
// incrementCount() {
// this.setState(preveState => {
// return {
// count: preveState.count + 1
// };
// });
// }
render() {
// let { count } = this.state;
return (
<div>
<h2 onMouseOver={this.props.incrementCount}>
{this.props.name} Hovered {this.props.count} times
</h2>
</div>
);
}
}
export default UpdatedComponent(HoverCounter);
WithCounter组件如下:
import React, { Component, useState, useEffect } from "react";
const UpdatedComponent = OriginalComponent => {
class NewComponent extends Component {
constructor() {
super();
this.state = {
count: 0
};
this.incrementCount = this.incrementCount.bind(this);
}
incrementCount() {
this.setState(preveState => {
return {
count: preveState.count + 1
};
});
}
render() {
return (
<OriginalComponent
name="Abdulla"
count={this.state.count}
incrementCount={this.incrementCount}
/>
);
}
}
return NewComponent;
};
export default UpdatedComponent;
总结起来,HOC的作用是为了精简代码,实现代码的复用.