forked from kay-is/react-from-zero
-
Notifications
You must be signed in to change notification settings - Fork 0
/
12-component-refactor.html
138 lines (113 loc) · 3.28 KB
/
12-component-refactor.html
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
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
<!doctype html>
<title>12 Component Refactor - React From Zero</title>
<script src="https://unpkg.com/react@15.4.2/dist/react.js"></script>
<script src="https://unpkg.com/react-dom@15.4.2/dist/react-dom.js"></script>
<script src="https://unpkg.com/babel-core@5.8.38/browser.min.js"></script>
<div id="app"></div>
<script type="text/babel">
// Refactoring is another thing that is nice with React
// First we'll talk about refactoring one component into another
// if you're lucky, you can just change the implementation of a component
// and don't need to change anything at the call-site
// We start with a component that renders records somehow
function ViewBefore(props) {
return (
<table>
<thead>
<tr>
<th>Room</th>
<th>People</th>
</tr>
</thead>
<tbody>
{props.rooms.map(function(room, k) {
return <tr key={k}>
<td>{room.name}</td>
<td>{room.people}</td>
</tr>
})}
</tbody>
</table>
)
}
// The component has a simple props-interface
ViewBefore.propTypes = {
rooms: React.PropTypes.array.isRequired,
}
// Now we switch out the implementation with something more complicated
function ViewAfter(props) {
return (
<div>
{props.rooms.map(function(room, k) {
var barStyle = {
display: 'inline-block',
background: 'lightgrey',
width: room.people * 25,
}
return <div key={k}>
{room.people > 0
? <span style={barStyle}>{room.people} People</span>
: <span>0 People</span>
}
<span> in {room.name}</span>
</div>
})}
</div>
)
}
// We keep the props-interface the same
ViewAfter.propTypes = {
rooms: React.PropTypes.array.isRequired,
}
// We could also switch it with something more dynamic
var ViewDynamic = React.createClass({
// We still keep the props-interface the same
propTypes: {
rooms: React.PropTypes.array.isRequired,
},
getInitialState: function() {
return {currentRoom: 0}
},
componentDidMount() {
var component = this
var props = this.props
this.interval = setInterval(function() {
var currentRoom = component.state.currentRoom < props.rooms.length - 1
? component.state.currentRoom + 1
: 0
component.setState({currentRoom: currentRoom})
}, 1000)
},
componentWillUnmount() {
clearInterval(this.interval)
},
render: function() {
var room = this.props.rooms[this.state.currentRoom]
return (
<span style={{color: this.state.color}}>
Room <b>{room.name}</b> has <b>{room.people}</b> People.
</span>
)
},
})
// Some data
var rooms = [
{name:'Office', people: 10},
{name:'Kitchen', people: 15},
{name:'Floor', people: 3},
{name:'Bathroom', people: 0},
]
// As we can see the components can be used exactly the same
// If we copy the implementation of ViewAfter into ViewBefore,
// everything keeps working
var reactElement =
<div style={{margin: 'auto', width: 500}}>
<h3>Before the refactor</h3>
<ViewBefore rooms={rooms}/>
<h3>After the refactor</h3>
<ViewAfter rooms={rooms}/>
<h3>Dynamic refactor</h3>
<ViewDynamic rooms={rooms}/>
</div>
ReactDOM.render(reactElement, document.getElementById('app'))
</script>