Skip to content

Instantly share code, notes, and snippets.

@jrf0110
Created May 19, 2017 16:40
Show Gist options
  • Save jrf0110/1847b6c51c252eddbc665b58976dab02 to your computer and use it in GitHub Desktop.
Save jrf0110/1847b6c51c252eddbc665b58976dab02 to your computer and use it in GitHub Desktop.
class AppState {
constructor(attrs) {
this.attrs = attrs || {
todos: []
}
}
clone() {
const attrs = Object.assign({}, this.attrs)
attrs.todos = attrs.todos.map(todo => Object.assign({}, todo))
return new AppState(attrs)
}
addTodo(todo) {
const this_ = this.clone()
todo.id = (Math.random() * 99999).toString(36)
this_.attrs.todos.push(todo)
return this_
}
removeTodo(todo) {
const this_ = this.clone()
this_.attrs.todos = this.attrs.todos.filter(todo => todo !== todo)
return this_
}
completeTodo(todo) {
const this_ = this.clone()
const i = this.attrs.todos.indexOf(todo)
this_.attrs.todos[i].complete = true
return this_
}
}
class TodoList extends React.Component {
static Item(props) {
const { todo, onCompletionToggleRequest, onRemoveTodoRequest } = props
const classes = ['todo-list-item']
if (todo.completed) {
classes.push('todo-list-item-completed')
}
return (
<div className={classes.join(' ')}>
<div className="todo-list-item-col todo-list-item-col-complete">
<input
type="checkbox"
checked={todo.completed}
onChange={onCompletionToggleRequest}
/>
</div>
<div className="todo-list-item-col todo-list-item-col-text">
{todo.text}
</div>
<div className="todo-list-item-col todo-list-item-col-remove">
<button onClick={onRemoveTodoRequest}>x</button>
</div>
</div>
)
}
render() {
return (
<div className="todo-list">
{this.props.todos
.map(todo => {
return (
<TodoList.Item
todo={todo}
onCompletionToggleRequest={() => this.props.onCompletionToggleRequest(todo)}
onRemoveTodoRequest={() => this.props.onRemoveTodoRequest(todo)}
key={todo.id}
/>
)
})
}
</div>
)
}
}
class TodoCreator extends React.Component {
constructor(props) {
super(props)
this.state = {
text: '',
}
this.onFormSubmit = this.onFormSubmit.bind(this)
this.onTextChange = this.onTextChange.bind(this)
}
render() {
return (
<form className="todo-creator" onSubmit={this.onFormSubmit}>
<input type="text" onChange={this.onTextChange} />
</form>
)
}
onFormSubmit(e) {
e.preventDefault()
this.props.onTodoSubmit({
text: e.target.value,
completed: false,
})
}
onTextChange(e) {
this.setState({ text: e.target.value })
}
}
class App extends React.Component {
constructor(props) {
super(props)
this.onCompletionToggleRequest = this.onCompletionToggleRequest.bind(this)
this.onTodoSubmit = this.onTodoSubmit.bind(this)
this.onRemoveTodoRequest = this.onRemoveTodoRequest.bind(this)
}
render() {
return (
<div className="app-todos">
<TodoCreator onTodoSubmit={this.onTodoSubmit} />
<TodoList
todos={this.props.todos}
onCompletionToggleRequest={this.onCompletionToggleRequest}
onRemoveTodoRequest={this.onRemoveTodoRequest}
/>
</div>
)
}
onCompletionToggleRequest(todo) {
this.props.changeState(state => state.completeTodo(todo))
}
onTodoSubmit(todo) {
this.props.changeState(state => state.addTodo(todo))
}
onRemoveTodoRequest(todo) {
this.props.changeState(state => state.removeTodo(todo))
}
}
let state = new AppState()
const changeState = fn => {
state = fn(state)
ReactDOM.render(
document.body,
<App ...state changeState={changeState} />
)
}
changeState(state => state)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment