Why React is a game changer
in frontend development
React fundamentally changes an equation we've all been working with for years, and an idea can be much more powerful than the technology implementing it.
Nicholas C. Zakas
Efficiency - you can end up creating memory leaks by losing track of node references or by forgetting to detach event handlers
Complexity - hard to maintain, hard to understand
event handlers attach/detach automatically -> no more memory leaks
we do much less manually -> apps are simpler and more scalable
declarative code -> easy to reason about
components -> reusability, encapsulation, testability
UI development is standardised
<span id="colored-counter">0</span>
<input id="color" placeholder="color">
<button id="inc">increase</button>
<script>
$('#color').on('keyup', function () {
$('#colored-counter').css('color', this.value);
})
$('#inc').on('click', function () {
var oldValue = $('#colored-counter').html();
var newValue = 1 + Number(oldValue);
$('#colored-counter').html(newValue);
})
</script>
<span id="colored-counter">0</span>
<input id="color" placeholder="color">
<button id="inc">increase</button>
<script>
var state = {color: '', value: 0};
function updateUI() {
$('#colored-counter').css('color', state.color);
$('#colored-counter').html(state.value);
}
$('#color').on('keyup', function () {
state.color = this.value;
updateUI();
})
$('#inc').on('click', function () {
state.value++;
updateUI();
})
</script>
Simple way: is really simple
“React” way: looks over-engineered
Simple way: is not that simple anymore
“React” way: suddenly it's simple now!
<span id="colored-counter">0</span>
<input id="color" placeholder="color">
<button id="inc">increase</button>
<script>
var state = {color: '', value: 0};
function updateUI() {
$('#colored-counter').css('color', state.color);
$('#colored-counter').html(state.value);
window.requestAnimationFrame(updateUI);
}
$('#color').on('keyup', function () {
state.color = this.value;
});
$('#inc').on('click', function () {
state.value++;
});
updateUI();
</script>
var ColoredCounter = React.createClass({
getInitialState: function() {
return { color: '', value: 0 };
},
onColorChange: function(e) {
this.setState({ color: e.target.value });
},
onValueChange: function() {
this.setState({ value: this.state.value + 1 });
},
render: function() {
return (
<div>
<span style={{ color: this.state.color }}>{ this.state.value }</span>
<input placeholder="color" onKeyUp={ this.onColorChange } />
<button onClick={ this.onValueChange }>increase</button>
</div>
);
}
});
ReactDOM.render(<ColoredCounter />, document.getElementById('app'));
var ColoredCounter = React.createClass({
getInitialState: function() {
return { color: '', value: 0 };
},
onColorChange: function(e) {
this.setState({ color: e.target.value });
},
onValueChange: function() {
this.setState({ value: this.state.value + 1 });
},
render: function() {
return (
<div>
<span style={{ color: this.state.color }}>{ this.state.value }</span>
<input placeholder="color" onKeyUp={ this.onColorChange } />
<button onClick={ this.onValueChange }>increase</button>
</div>
);
}
});
ReactDOM.render(<ColoredCounter />, document.getElementById('app'));
//...
render: function() {
return (
<div>
<span style={{ color: this.state.color }}>{ this.state.value }</span>
<input placeholder="color" onKeyUp={ this.onColorChange } />
<button onClick={ this.onValueChange }>increase</button>
</div>
);
}
//...
const $ = React.createElement;
//...
render: function() {
return (
$('div', null,
$('span', { style: { color: this.state.color } }, this.state.value),
$('input', { placeholder: 'color', onKeyUp: this.onColorChange }),
$('button', { onClick: this.onValueChange }, 'increase')
)
);
}
//...
encapsulated DOM structure
encapsulated DOM logic
automated DOM interactions
highly reusable
var ColoredCounter = React.createClass({
getInitialState: function() {
return { color: '', value: 0 };
},
onColorChange: function(e) {
this.setState({ color: e.target.value });
},
onValueChange: function() {
this.setState({ value: this.state.value + 1 });
},
render: function() {
return (
<div>
<span style={{ color: this.state.color }}>{ this.state.value }</span>
<input placeholder="color" onKeyUp={ this.onColorChange } />
<button id="inc" onClick={ this.onValueChange }>increase</button>
</div>
);
}
});
ReactDOM.render(<ColoredCounter />, document.getElementById('app'));
class ColoredCounter extends React.Component {
constructor(props) {
super(props);
this.state = { color: '', value: 0 };
}
onColorChange = e => {
this.setState({ color: e.target.value });
};
onValueChange = () => {
this.setState({ value: this.state.value + 1 });
};
render() {
return (
<div>
<span style={{ color: this.state.color }}>{ this.state.value }</span>
<input placeholder="color" onKeyUp={ this.onColorChange } />
<button id="inc" onClick={ this.onValueChange }>increase</button>
</div>
);
}
}
ReactDOM.render(<ColoredCounter />, document.getElementById('app'));
<div class="entry">
<h1>{{title}}</h1>
<div class="body">
{{body}}
</div>
{{#each comments}}
<h2>By {{fullName author}}</h2>
<div class="comment">{{text}}</div>
{{/each}}
</div>
<div class="entry">
<h1>{{title}}</h1>
<div class="body">
{{body}}
</div>
{{#each comments}}
<h2>By {{fullName author}}</h2>
<div class="comment">{{text}}</div>
{{/each}}
<form>
<textarea></textarea>
<button>Add new comment</button>
</form>
</div>
<div class="entry">
<h1>{{title}}</h1>
<div class="body">
{{body}}
</div>
{{#each comments}}
<h2>By {{fullName author}}</h2>
<div class="comment">{{text}}</div>
{{/each}}
<form id="newComment">
<textarea id="commentText"></textarea>
<button>Add new comment</button>
</form>
</div>
<div class="entry">
<h1>{{title}}</h1>
<div class="body">
{{body}}
</div>
{{#each comments}}
<h2>By {{fullName author}}</h2>
<div class="comment">{{text}}</div>
{{/each}}
<form id="{{commentFormID}}">
<textarea id="{{commentFormTextID}}"></textarea>
<button>Add new comment</button>
</form>
</div>
<div class="entry">
<h1>{{title}}</h1>
<div class="body">
{{body}}
</div>
{{#each comments}}
<h2>By {{fullName author}}</h2>
<div class="comment">{{text}}</div>
{{/each}}
<form class="comment-form">
<textarea class="comment-text"></textarea>
<button>Add new comment</button>
</form>
</div>
No matter how you structure your project, there is no separation anymore
class ColoredCounter extends React.Component {
constructor(props) {
super(props);
this.state = { color: '', value: 0 };
}
onColorChange = e => {
this.setState({ color: e.target.value });
};
onValueChange = () => {
this.setState({ value: this.state.value + 1 });
};
render() {
return (
<div>
<span style={{ color: this.state.color }}>{ this.state.value }</span>
<input placeholder="color" onKeyUp={ this.onColorChange } />
<button id="inc" onClick={ this.onValueChange }>increase</button>
</div>
);
}
}
class ColoredCounter extends React.Component {
// constructor, event handlers, etc.
render() {
return (
<div>
<Counter color={this.state.color} value={this.state.value} />
<input placeholder="color" onKeyUp={ this.onColorChange } />
<button id="inc" onClick={ this.onValueChange }>increase</button>
</div>
);
}
}
class Counter extends React.Component {
render() {
return (
<span style={{ color: this.props.color }}>{ this.props.value }</span>
);
}
}
class ColoredCounter extends React.Component {
// constructor, event handlers, etc.
render() {
return (
<div>
<Counter color={this.state.color}>{this.state.value}</Counter>
<input placeholder="color" onKeyUp={ this.onColorChange } />
<button id="inc" onClick={ this.onValueChange }>increase</button>
</div>
);
}
}
class Counter extends React.Component {
render() {
return (
<span style={{ color: this.props.color }}>{ this.props.children }</span>
);
}
};
class ColoredCounter extends React.Component {
// constructor, event handlers, etc.
render() {
return (
<div>
<Counter color={this.state.color}>{this.state.value}</Counter>
<input placeholder="color" onKeyUp={ this.onColorChange } />
<button id="inc" onClick={ this.onValueChange }>increase</button>
</div>
);
}
}
const Counter = function(props) {
return <span style={{ color: props.color }}>{ props.value }</span>;
};
props
props
props
props
props
state
state
props
props
props
onChange
class DatePicker extends React.Component {
componentDidMount() {
$(this.refs.datepicker).datepicker();
}
render() {
return (
<p>
<input placeholder="click me" type="text" ref="datepicker" />
</p>
);
}
}
ReactDOM.render(<DatePicker />, document.getElementById('app'));
controlled/uncontrolled components
propTypes
context
dynamic children
server-side rendering
React Native
testing
...
They are great and you can use them, but...
community
automates manual work, less chances of mistakes
optimising DOM interactions -> great UI performance
simplifies data-flow and makes it predictable
works great for teams, enforcing to follow good patterns
declarative UI code is readable and maintainable
componentization is the future of web development
not opinionated about your app structure
huge community and ready-to-use components and modules
React is the best thing since XMLHttpRequest
James K. Nelson
Official links:
Documentation
Github
Github: https://github.com/mistadikay/
Twitter: https://twitter.com/mistadikay
E-mail: iam@mistadikay.com