forked from vasanthk/react-bits
-
Notifications
You must be signed in to change notification settings - Fork 0
/
08.HOC-for-styling.jsx
122 lines (109 loc) · 2.72 KB
/
08.HOC-for-styling.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
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
/**
* Using HOC for styling
* Sometimes there are isolated UI components that only require a minimal amount of state for interaction, and using them as standalone components is sufficient
* eg. Interactions in a Carousel
*
* @Reference:
* http://jxnblk.com/writing/posts/patterns-for-style-composition-in-react/
*/
// Example: Carousel
// The HOC will have a current slide index and have previous and next methods.
// Higher order component
import React from 'react'
// This could be named something more generic like Counter or Cycle
const CarouselContainer = (Comp) => {
class Carousel extends React.Component {
constructor() {
super();
this.state = {
index: 0
};
this.previous = () => {
const { index } = this.state;
if (index > 0) {
this.setState({index: index - 1})
}
};
this.next = () => {
const { index } = this.state;
this.setState({index: index + 1})
}
}
render() {
return (
<Comp
{...this.props}
{...this.state}
previous={this.previous}
next={this.next}/>
)
}
}
return Carousel
};
export default CarouselContainer;
// Using the HOC
// UI component
const Carousel = ({ index, ...props }) => {
const length = props.length || props.children.length || 0;
const sx = {
root: {
overflow: 'hidden'
},
inner: {
whiteSpace: 'nowrap',
height: '100%',
transition: 'transform .2s ease-out',
transform: `translateX(${index % length * -100}%)`
},
child: {
display: 'inline-block',
verticalAlign: 'middle',
whiteSpace: 'normal',
outline: '1px solid red',
width: '100%',
height: '100%'
}
};
const children = React.Children.map(props.children, (child, i) => {
return (
<div style={sx.child}>
{child}
</div>
)
});
return (
<div style={sx.root}>
<div style={sx.inner}>
{children}
</div>
</div>
)
};
// Final Carousel component
const HeroCarousel = (props) => {
return (
<div>
<Carousel index={props.index}>
<div>Slide one</div>
<div>Slide two</div>
<div>Slide three</div>
</Carousel>
<Button
onClick={props.previous}
children='Previous'/>
<Button
onClick={props.next}
children='Next'/>
</div>
)
};
// Wrap the component with the functionality from the higher order component
export default CarouselContainer(HeroCarousel)
// By keeping the styling separate from the interactive state, any number of carousel variations can be created from these reusable parts.
// Usage example
const Carousel = () => (
<div>
<HeroCarousel />
</div>
);