Created
July 4, 2016 15:43
-
-
Save ghigt/0deb97aa0cd8ffe5ddc1209fb7df82a7 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
* Extracting Action Creators | |
*/ | |
let nextTodoId = 1; | |
// This is our reducer for a single todo | |
const todo = (state, action) => { | |
switch (action.type) { | |
case 'ADD_TODO': | |
return { | |
id: action.id, | |
text: action.text, | |
completed: false | |
}; | |
case 'TOGGLE_TODO': | |
if (state.id !== action.id) { | |
return state; | |
} | |
return { | |
...state, | |
completed: !state.completed | |
} | |
default: | |
return state; | |
} | |
} | |
// This is our reducer for multiple todos | |
const todos = (state = [], action) => { | |
switch (action.type) { | |
case 'ADD_TODO': | |
return [ | |
...state, | |
todo(undefined, action) | |
]; | |
case 'TOGGLE_TODO': | |
return state.map(t => todo(t, action)) | |
default: | |
return state; | |
} | |
}; | |
// This is our reducer for the visibility | |
const visibilityFilter = (state = 'SHOW_ALL', action) => { | |
switch (action.type) { | |
case 'SET_VISIBILITY_FILTER': | |
return action.filter; | |
default: | |
return state; | |
} | |
}; | |
const addTodo = (text) => { | |
return { | |
type: 'ADD_TODO', | |
text, | |
id: nextTodoId++ | |
}; | |
}; | |
const setVisibilityFilter = (filter) => { | |
return { | |
type: 'SET_VISIBILITY_FILTER', | |
filter | |
}; | |
}; | |
const toggleTodo = (id) => { | |
return { | |
type: 'TOGGLE_TODO', | |
id | |
}; | |
}; | |
import { combineReducers } from 'redux'; | |
const todoApp = combineReducers({ | |
todos, | |
visibilityFilter | |
}); | |
import React, { Component, PropTypes } from 'react'; | |
import ReactDOM from 'react-dom'; | |
const Link = ({ active, children, onClick }) => { | |
if (active) { | |
return <span>{children}</span>; | |
} | |
return <a href="#" | |
onClick={e => { | |
e.preventDefault(); | |
onClick(); | |
}}> | |
{children} | |
</a>; | |
}; | |
const mapStateToLinkProps = (state, ownProps) => { | |
return { | |
active: ownProps.filter === state.visibilityFilter | |
}; | |
}; | |
const mapDispatchToLinkProps = (dispatch, ownProps) => { | |
return { | |
onClick: () => dispatch(setVisibilityFilter(ownProps.filter)) | |
}; | |
}; | |
const FilterLink = connect( | |
mapStateToLinkProps, | |
mapDispatchToLinkProps | |
)(Link) | |
const Footer = () => ( | |
<p> | |
Show: | |
{' '} | |
<FilterLink filter="SHOW_ALL">All</FilterLink> | |
{' '} | |
<FilterLink filter="SHOW_ACTIVE">Active</FilterLink> | |
{' '} | |
<FilterLink filter="SHOW_COMPLETED">Completed</FilterLink> | |
</p> | |
); | |
const Todo = ({ onClick, completed, text }) => ( | |
<li onClick={onClick} | |
style={{ textDecoration: completed ? 'line-through' : 'none' }}> | |
{text} | |
</li> | |
); | |
const TodoList = ({ todos, onTodoClick }) => ( | |
<ul> | |
{todos.map(todo => | |
<Todo key={todo.id} | |
onClick={() => onTodoClick(todo.id)} | |
{...todo} /> | |
)} | |
</ul> | |
); | |
let AddTodo = ({ dispatch }) => { | |
let input; | |
return <div> | |
<input ref={node => {input = node}} /> | |
<button type="button" | |
onClick={() => { | |
dispatch(addTodo(input.value)); | |
input.value = ''; | |
}}> | |
Add Todo | |
</button> | |
</div>; | |
}; | |
AddTodo = connect()(AddTodo); | |
const getVisibleTodos = (todos = [], filter) => { | |
switch (filter) { | |
case 'SHOW_ALL': | |
return todos; | |
case 'SHOW_COMPLETED': | |
return todos.filter(t => t.completed); | |
case 'SHOW_ACTIVE': | |
return todos.filter(t => !t.completed); | |
default: | |
return todos; | |
}; | |
}; | |
const mapStateToTodoListProps = (state) => { | |
return { | |
todos: getVisibleTodos( | |
state.todos, | |
state.visibilityFilter | |
) | |
}; | |
}; | |
const mapDispatchToTodoListProps = (dispatch) => { | |
return { | |
onTodoClick: (id) => { | |
dispatch(toggleTodo(id)) | |
} | |
}; | |
}; | |
import { connect } from 'react-redux'; | |
const VisibleTodoList = connect( | |
mapStateToTodoListProps, | |
mapDispatchToTodoListProps | |
)(TodoList); | |
const TodoApp = () => ( | |
<div> | |
<AddTodo /> | |
<VisibleTodoList /> | |
<Footer /> | |
</div> | |
); | |
import { Provider } from 'react-redux'; | |
import { createStore } from 'redux'; | |
ReactDOM.render( | |
<Provider store={createStore(todoApp)}> | |
<TodoApp /> | |
</Provider>, | |
document.getElementById('root') | |
); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment