Files
react-from-zero/12-component-refactor.html
2018-06-05 08:29:12 +02:00

138 lines
3.4 KiB
HTML

<!doctype html>
<title>12 Component Refactor - React From Zero</title>
<script src="https://unpkg.com/react@16.4.0/umd/react.development.js"></script>
<script src="https://unpkg.com/react-dom@16.4.0/umd/react-dom.development.js"></script>
<script src="https://unpkg.com/create-react-class@15.6.3/create-react-class.js"></script>
<script src="https://unpkg.com/prop-types@15.6.1/prop-types.js"></script>
<script src="https://unpkg.com/@babel/standalone/babel.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: 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: PropTypes.array.isRequired,
}
// We could also switch it with something more dynamic
var ViewDynamic = createReactClass({
// We still keep the props-interface the same
propTypes: {
rooms: 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>