The art of
Higher-Order Component
黃駿朋 / dmoon / DMoon
中央資工研究所
創科資訊
dmoon.t@gmail.com
Blog
GitHub
React Native Taiwan (http://reactnative.asia)
How many of you have heard of HOC?
Add functionality to existing component classes
Why HOCs are useful?
Reusing component logic
Add reusing functionality to existing component classes
Higher-Order Component?
Higher-Order Function
Functional Programming
Function As Parameter
Higher-Order Function
A higher order function is a function that takes a function as an argument, or returns a function
A higher-order component is a function that takes a component and returns a new component.
Higher-Order Component
function HOC(WrappedComponent) {
// abstract logic
return <WrappedComponent enhanced={true} />;
}
const EnhancedComponent = HOC(WrappedComponent);
function HOC(WrappedComponent) {
// returns another component
return class extends React.Component {
// constructor or lifecycle methods...
render() {
// ... and renders the wrapped component with the fresh data!
// Notice that we pass through any additional props
return <WrappedComponent data={this.state.data}
{...this.props} />;
}
}
}
const EnhancedComponent = HOC(WrappedComponent);
Props Proxy
Inheritance Inversion
function HOC(WrappedComponent) {
return class Enhancer extends WrappedComponent {
render() {
return super.render()
}
}
}
const EnhancedComponent = HOC(WrappedComponent);
Render Highjacking
Examples
React-Redux
connect
connect components to Redux store
const EnhancedComp = connect(mapStateToProps)(MyComp);
HOC(MyComp);
Curry
Custom HOC
LikeButton
/* HOC */
export default WrappedComponent => class Optimistic extends Component {
state = {
isActive: this.props.isActive
}
handleOnPress = async () => {
// optimistic update
const originStatus = this.state.isActive;
this.setState({ isActive: !originStatus });
// do fetch
let isSuccess;
if (this.state.isActive) {
isSuccess = await this.props.inactivate();
} else {
isSuccess = await this.props.activate();
}
if (!isSuccess) {
this.setState({ isActive: originStatus });
}
}
render() {
return <WrappedComponent
{...this.props}
isActive={this.state.isActive}
onPress={this.handleOnPress} />;
}
};
Title Text
/* Usage */
const OptimisticLikeBtn = Optimistic(LikeButton);
export default class LikeButton extends Component {
like = async () => {
const response = await likeRequest;
return response.isSuccess;
}
unlike = async () => {
const response = await unlikeRequest;
return response.isSuccess;
}
render() {
return (
<OptimisticLikeBtn
{...this.props}
isActive={this.props.isCollected}
activate={this.like}
inactivate={this.unlike} />
);
}
}
Q & A
The art of Higher-Order Component
By dmoon
The art of Higher-Order Component
- 1,301