forked from binler/react-bits
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy path15.higher-order-component.jsx
100 lines (84 loc) · 2.86 KB
/
15.higher-order-component.jsx
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
/**
* A higher-order function is a function that takes and/or returns a function. It’s not more complicated than that. So, what’s a higher-order component?
* If you’re already using container components, these are just generic containers, wrapped up in a function.
*
* Higher-order components look really similar to the decorator design pattern.
* It is wrapping a component and attaching some new functionalities or props to it.
*/
/**
* SIMPLE EXAMPLE
*/
// HOC
import { Component } from "React";
export var Enhance = ComposedComponent => class extends Component {
constructor() {
this.state = { data: null };
}
componentDidMount() {
this.setState({ data: 'Hello' });
}
render() {
return <ComposedComponent {...this.props} data={this.state.data} />;
}
};
// HOC Usage
import { Enhance } from "./Enhance";
class MyComponent {
render() {
if (!this.data) return <div>Waiting...</div>;
return <div>{this.data}</div>;
}
}
export default Enhance(MyComponent); // Enhanced component
/**
* MORE DETAILED
*/
// Let’s start with our stateless Greeting component.
const Greeting = ({ name }) => {
if (!name) { return <div>Connecting...</div> }
return <div>Hi {name}!</div>
};
// If it gets props.name, it’s gonna render that data. Otherwise it’ll say that it’s “Connecting…”.
// Now for the higher-order bit.
const Connect = ComposedComponent =>
class extends React.Component {
constructor() {
super();
this.state = { name: "" }
}
componentDidMount() {
// this would fetch or connect to a store
this.setState({ name: "Michael" })
}
render() {
return (
<ComposedComponent
{...this.props}
name={this.state.name}
/>
)
}
};
// This is just a function that returns component that renders the component we passed as an argument.
// Last step, we need to wrap our our Greeting component in Connect.
const ConnectedMyComponent = Connect(Greeting);
// This is a powerful pattern for providing fetching and providing data to any number of stateless function components.
// Advantage of using HOC:
// HOCs give us control on the input data that we want to send as props.
// Let's say that we have a configuration setting that OriginalComponent needs:
var config = require('path/to/configuration');
var enhanceComponent = (Component) =>
class Enhance extends React.Component {
render() {
return (
<Component
{...this.state}
{...this.props}
title={ config.appTitle }
/>
)
}
};
// The knowledge for the configuration is hidden into the higher-order component.
// OriginalComponent knows only that it receives a prop called title. Where it comes from it is not important.
// That's a huge advantage because it helps us testing the component in an isolation and provides nice mechanism for mocking.