Skip to content

Instantly share code, notes, and snippets.

@dawncold
Created November 30, 2015 10:29
Show Gist options
  • Save dawncold/8f8c32aaf263000e35d0 to your computer and use it in GitHub Desktop.
Save dawncold/8f8c32aaf263000e35d0 to your computer and use it in GitHub Desktop.
React todo mvc
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8"/>
<title>Hello React!</title>
<style>
li.todo-item.completed span {
text-decoration: line-through;
}
</style>
</head>
<body>
<div id="example"></div>
<script src="{{ static_url('mobile/js/r/bundle.js') }}"></script>
</body>
</html>
var React = require('react');
var ReactDOM = require('react-dom');
var classNames = require('classnames');
var director = require('director');
var TodoInput = React.createClass({
getInitialState: function () {
"use strict";
return {input: ''};
},
changeHandler: function (e) {
"use strict";
this.setState({input: e.target.value.trim()});
},
addHandler: function (e) {
"use strict";
e.preventDefault();
var todo = {id: (new Date()).getTime(), text: this.state.input, completed: false};
this.props.onTodoAdded(todo);
this.setState({input: ''});
},
render: function () {
"use strict";
return (
<form className="add-todo-form" onSubmit={this.addHandler}>
<input type="text" onChange={this.changeHandler} value={this.state.input} placeholder="add something..."/>
</form>
);
}
});
var TodoItem = React.createClass({
getInitialState: function () {
"use strict";
return {editing: false, text: this.props.todo.text}
},
handleStateChange: function (e) {
"use strict";
this.props.onItemStateChanged(e.target.checked);
},
handleItemEdit: function () {
"use strict";
if (!this.props.todo.completed) {
this.setState({editing: true});
}
},
handleTextChange: function (e) {
"use strict";
if (this.state.editing) {
this.setState({text: e.target.value});
}
},
handleItemEditSubmit: function (e) {
"use strict";
e.preventDefault();
var todo = this.props.todo;
todo.text = this.state.text;
this.props.onItemEditSubmit(todo);
this.setState({editing: false});
},
render: function () {
"use strict";
var todoItemClassNames = classNames('todo-item', {
completed: this.props.todo.completed
});
var todoContent;
if (this.state.editing) {
todoContent = (
<form className="edit-todo" onSubmit={this.handleItemEditSubmit}>
<input type="text" value={this.state.text} onChange={this.handleTextChange}/>
</form>
);
} else {
todoContent = (
<li className={todoItemClassNames}>
<input type="checkbox" onChange={this.handleStateChange} checked={this.props.todo.completed}/>
<span onDoubleClick={this.handleItemEdit}>{this.props.todo.text}</span>
<a href="#" onClick={this.props.onDeleted}>[ X ]</a>
</li>
);
}
return todoContent;
}
});
var TodoList = React.createClass({
render: function () {
var todos = this.props.data.map(function (todo) {
"use strict";
return (
<TodoItem
key={todo.id}
todo={todo}
onItemEditSubmit={this.props.onItemEditSubmit}
onItemStateChanged={this.props.onItemStateChanged.bind(null, todo)}
onDeleted={this.props.onDeleted.bind(null, todo)}
/>
);
}, this);
return (
<ul>
{todos}
</ul>
);
}
});
var TodoFooter = React.createClass({
render: function () {
return (
<div>
Total: {this.props.data.length}
<a href="#/">All</a>&nbsp;&nbsp;
<a href="#/active">Active</a>&nbsp;&nbsp;
<a href="#/completed">Completed</a>&nbsp;&nbsp;
</div>
);
}
});
var app = app || {};
app.ALL = 'all';
app.ACTIVE = 'active';
app.COMPLETED = 'completed';
var TodoApp = React.createClass({
getInitialState: function () {
"use strict";
return {todo: [], show: app.ALL};
},
componentDidMount: function () {
"use strict";
var setState = this.setState;
var routers = director.Router({
'/': setState.bind(this, {show: app.ALL}),
'/active': setState.bind(this, {show: app.ACTIVE}),
'/completed': setState.bind(this, {show: app.COMPLETED})
});
routers.init('/');
},
handleNewTodo: function (todo) {
"use strict";
var todos = this.state.todo;
this.setState({todo: todos.concat(todo)});
},
handleItemStateChanged: function (changedItem, state) {
"use strict";
this.setState({
todo: this.state.todo.map(function(todo) {
if (todo.id === changedItem.id) {
todo.completed = state;
}
return todo;
})
});
},
handleDelete: function (todoToDelete) {
"use strict";
this.setState({
todo: this.state.todo.filter(function (todo) {
return todo.id !== todoToDelete.id;
})
});
},
handleItemEditSubmit: function (editedTodo) {
"use strict";
this.setState({
todo: this.state.todo.map(function (todo) {
if (todo.id === editedTodo.id) {
todo.text = editedTodo.text
}
return todo;
})
});
},
render: function(){
"use strict";
var show = this.state.show;
var todos = this.state.todo.filter(function (todo) {
if (show === app.ALL) {
return true;
} else if (show === app.ACTIVE) {
return !todo.completed;
} else if (show === app.COMPLETED) {
return todo.completed;
}
});
return (
<div>
<TodoInput onTodoAdded={this.handleNewTodo}/>
<TodoList
data={todos}
onItemStateChanged={this.handleItemStateChanged}
onDeleted={this.handleDelete}
onItemEditSubmit={this.handleItemEditSubmit}
/>
<TodoFooter data={todos} />
</div>
);
}
});
ReactDOM.render(
<TodoApp />,
document.getElementById('example')
);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment