More Related Content Similar to Frontin like-a-backer (20) Frontin like-a-backer17. This is not separation of concerns.
<a class="hide-me">Click and I'll disappear</a>
<script type="application/javascript">
$('a.hide_me').on('click', function (e) {
e.preventDefault();
$(this).hide();
});
</script>
It's error-prone.
22. We need:
1. Generated Elements; Templates?
2. XHR requests; Obviously, it's the future.
3. Data Handling; Models? Collections?
24. Backbone.JS: You figure it out.
var DocumentRow = Backbone.View.extend({
tagName: "li",
className: "document-row",
events: {
"click .icon": "open",
},
initialize: function() {
this.listenTo(this.model, "change", this.render);
},
render: function() {
var idea = 'I have none';
}
});
34. Why can't it just be like that?
Just the UI
Just like HTML
36. Define
var HelloWorld = React.createClass({
render: function () {
return <h1>Hello, World!</h1>;
}
});
Use
React.render(
<HelloWorld/>,
document.getElementById('root')
);
41. Desugared
var HelloWorld = React.createClass({
render: function () {
return React.createElement(
'h1',
{className: 'hello_world'},
'Hello, World!'
);
}
});
44. Just like HTML:
It's composable.
<ModalWindow>
<ModalHeader title="Hello World"/>
<ModalBody>
...
</ModalBody>
</ModalWindow>
46. But where do I put my data?
React is all about the bass UI.
49. var Badge = React.createClass({
render: function () {
return <div className="badge">
<h1>{this.props.name}</h1>
<div>;
}
});
React.render(
<Badge name="Kayla" />,
document.getElementById('root')
);
50. var Badge = React.createClass({
render: function () {
var description = this.props.is_awesome
? 'is awesome!'
: 'is not awesome';
return <div className="badge">
<h1>{this.props.text}</h1>
<p>
{description}
</p>
<div>;
}
});
React.render(<Badge name="Kayla" is_awesome={true} />, rootNode);
51. var BadgeList = React.createClass({
render: function () {
var badges = this.props.people.map(function (person) {
return <Badge key={person.id} {...person} />;
});
return <div className="badge_list">{badges}<div>;
}
});
React.render(<BadgeList people={peopleCollection} />, rootNode);
53. var Toggle = React.createClass({
getInitialState: function () {
return { completed: false };
},
render: function () {
var className = this.state.completed
? 'toggle--completed'
: 'toggle';
return <div className={className} />;
}
});
54. var Toggle = React.createClass({
getInitialState: function () {
return { completed: false };
},
onClick: function () {
this.setState({completed: ! this.state.completed});
},
render: function () {
var className = this.state.completed
? 'toggle--completed'
: 'toggle';
return <div onClick={this.onClick} className={className} />;
}
});
56. Back-end data flow:
1. Receive an HTTP request.
2. Process + Get relevant data.
3. Respond with a rendered view.
65. Flux is only a pattern
There are many implementations already.
74. // stores/TodoStore.js
import alt from '../alt';
import TodoActions from '../actions/TodoActions';
class TodoStore {
constructor() {
this.todos = [];
this.bindListeners({
handleCreatedTodo: TodoActions.CREATE_TODO
});
}
handleCreatedTodo (todo) {
this.todos.push(todo);
}
}
export default alt.createStore(TodoStore, 'TodoStore');
75. import React from 'react';
var TodoApplication = React.createClass({
render() {
var todoList = this.state.todos.map(function (todo, index) {
return <li key={index}>{todo.task}</li>;
});
return <div className="todos">
<ul className="todo__list">
{todoList}
</ul>
<input type="text"/>
</div>;
}
});
76. import TodoStore from '../stores/TodoStore';
var TodoApplication = React.createClass({
componentWillMount () {
TodoStore.listen(this.handleChange);
}
componentWillUnmount () {
TodoStore.unlisten(this.handleChange);
}
handleChange (state) {
this.setState(state);
}
getInitialState() {
return TodoStore.getState();
}
});
77. var TodoApplication = React.createClass({
render() {
var todoList = this.state.todos.map(function (todo, index) {
return <li key={index}>{todo.task}</li>;
});
return <div className="todos">
<ul className="todo__list">
{todoList}
</ul>
<input type="text"/>
</div>;
}
});
78. var TodoList = React.createClass({
render() {
var todoList = this.props.todos.map(function (todo, index) {
return <li key={index}>{todo.task}</li>;
});
return <ul className="todo__list">
{todoList}
</ul>;
}
});
79. import TodoList from './TodoList';
var TodoApplication = React.createClass({
render() {
return <div className="todos">
<TodoList todos={this.state.todos} />
<input type="text"/>
</div>;
}
});
80. import TodoList from './TodoList';
import TodoActions from '../actions/TodoActions';
var TodoApplication = React.createClass({
handleCreateTodo (event) {
if (event.keyCode !== 13) return;
var task = event.target.value;
TodoAction.createTodo(task);
}
render() {
return <div className="todos">
<TodoList todos={this.state.todos} />
<input type="text" onKeyDown={this.handleCreateTodo}/>
</div>;
}
});
83. import alt from '../alt';
import TodoActions from '../actions/TodoActions';
class TodoStore {
handleCreatedTodo (todo) {
fetch('/todos', {
method: 'post',
body: JSON.stringify(todo)
}).then((response) => {
this.todos.push(response.json());
this.emitChange();
});
}
}
export default alt.createStore(TodoStore, 'TodoStore');