Just shut up about it already, Pete
Not a templating engine!
“The degree to which each program module relies on each of the other modules.”
“The degree to which elements of a module belong together”
App.SayHello = Ember.Component.extend({
actions: {
hello: function() {
alert('Hello ' + this.get('name'));
}
}
});
Component class
<script type="text/x-handlebars" data-template-name="say-hello">
<button {{action 'hello'}}>
Say Hello to {{name}}
</button>
</script>
Handlebars template
var SayHello = React.createClass({
onClick: function(event) {
alert('Hello ' + this.props.name);
},
render: function() {
return (
<button onClick={this.onClick}>
Say Hello to {this.props.name}
</button>
);
}
});
Component Class
The key design decision that makes React awesome
Mutable DOM
Mutable data
User input
Asynchronous API requests
Browser request
Fetch data from DB
Pass data to template
Template renders page
User input
Fetch data from API
Pass data to top component
React renders component tree
Traditional Rendering
React Rendering
They describe your UI at any point in time.
DOM manipulation is slow
React builds a virtual DOM tree
Diffs the tree with the previous tree
Computes the minimal set of DOM mutations
Batch executes from the mutation queue
Isomorphic applications with shared components
Render initial state for search indexing and caching
React will start from initial state without re-rendering
var HelloWorld = React.createClass({
render: function() {
return <p>Hello {this.props.name}</p>;
}
});
React.render(
<HelloWorld name="John" />,
document.getElementById("app")
);
Rendering the component on the page:
Concise & familiar syntax for defining tree structures
<p className="hello">
Hello {this.props.name}
</p>
React.createElement("p", {className: "hello"},
"Hello ", this.props.name
)
Compiles to a React factory method:
<p className={this.props.className}>
Hello {this.props.name.toUpperCase()}!
</p>
React.createElement("p", {className: this.props.className},
"Hello ", this.props.name.toUpperCase(), "!"
)
<p>
Hello <a href="https://www.localmed.com">LocalMed</a>
</p>
React.createElement("p", null,
"Hello ",
React.createElement("a", {href: "https://www.localmed.com"},
"LocalMed"
)
)
var ClickCounter = React.createClass({
getInitialState: function() {
return {clickCount: 0};
},
onClick: function() {
this.setState({clickCount: this.state.clickCount + 1});
},
render: function() {
return (
<p onClick={this.onClick}>
Clicks: {this.state.clickCount}
</p>
);
}
});
Owned by parent
Changed by parent
Preferred
Owned by component
Changed by component
Avoided
Props
State
var ClickApp = React.createClass({
getInitialState: function() {
return {clickCount: 0};
},
onClick: function() {
this.setState({clickCount: this.state.clickCount + 1});
},
render: function() {
return (
<div>
<h2>Click App</h2>
<a onClick={this.onClick}>Click me!</a>
<ClickCount count={this.state.clickCount} />
</div>
);
}
});
var ClickCount = React.createClass({
render: function() {
return <p>Clicks: {this.props.count}</p>;
}
});
var ClickCount = React.createClass({
propTypes: {
count: React.PropTypes.number.isRequired
},
render: function() {
return <p>Clicks: {this.props.count}</p>;
}
});
It complements React’s composable view components by utilizing a unidirectional data flow.
Unfortunately, there’s no clear winner
Fluxxor
Reflux
Delorean
Fluxy
Marty
…