Navigation Menu

Skip to content

Instantly share code, notes, and snippets.

@gpltaylor
Created October 22, 2016 09:49
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save gpltaylor/62f576a72f9326305f9e9ca58c42beb1 to your computer and use it in GitHub Desktop.
Save gpltaylor/62f576a72f9326305f9e9ca58c42beb1 to your computer and use it in GitHub Desktop.
<!DOCTYPE html>
<html>
<head>
<meta name="description" content="[Todo App]">
<script src="//fb.me/react-0.14.3.js"></script>
<script src="//fb.me/react-dom-0.14.3.js"></script>
<script src="https://wzrd.in/standalone/expect@latest"></script>
<script src="https://wzrd.in/standalone/deep-freeze@latest"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/redux/3.0.5/redux.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-redux/4.0.6/react-redux.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/babel-core/5.8.23/browser.min.js"></script>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<title>JS Bin</title>
</head>
<body>
<div id='root'></div>
<script type="text/babel">
const { combineReducers, createStore } = Redux;
const { Provider, connect } = ReactRedux;
const { Component } = React;
const setVisibilityFilter = (filter) => ({type: 'SET_VISIBILITY_FILTER', filter})
const toggleTodo = (id) => ({type: 'TOGGLE_TODO', id})
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;
}
};
const todos = (state = [], action) => {
var retState;
switch (action.type) {
case 'ADD_TODO':
retState = [...state, todo(undefined, action)];
return retState;
case 'TOGGLE_TODO':
retState = state.map(t => todo(t, action));
return retState
default:
return state;
}
};
const visibilityFilter = (state = 'SHOW_ALL', action) => {
switch (action.type) {
case 'SET_VISIBILITY_FILTER':
return action.filter;
default:
return state;
}
};
const todoApp = combineReducers({todos, visibilityFilter});
//==============================================
const Link = ({active, children, onLinkClick}) => {
if (active) {
return <span>{children}</span>
}
return (
<a href='#' onClick={e => {
e.preventDefault();
onLinkClick();
}}>
{children}
</a>
)
}
const mapStateToLinkProps = (state, ownProps) => (
{active: ownProps.filter === state.visibilityFilter}
)
const mapDispatchToLinkProps = (dispatch, ownProps) => (
{onLinkClick: () => dispatch(setVisibilityFilter(ownProps.filter))}
)
const FilterLink = connect(mapStateToLinkProps, mapDispatchToLinkProps)(Link);
const Footer = ({store}) => (
<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} {...todo} onClick={() => onTodoClick(todo.id)} />
)}
</ul>
)
const mapStateToListProps = (state) => ({todos: getVisibleTodos(state.todos, state.visibilityFilter)})
const mapDispatchToListProps = (dispatch) => ({onTodoClick: (id) => dispatch(toggleTodo(id))})
const VisibleTodoList = connect(mapStateToListProps, mapDispatchToListProps)(TodoList)
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);
}
}
let nextTodoId = 0;
const addTodo = (text) => {return {type: 'ADD_TODO', id: nextTodoId++, text};};
let AddTodo = ({dispatch}) => {
let input;
return (
<div>
<input ref={node => input = node} />
<button onClick={() => {
dispatch(addTodo(input.value));
input.value = '';
}}>
Add Todo
</button>
</div>
);
}
AddTodo = connect()(AddTodo);
const TodoApp = () => (
<div>
<AddTodo />
<VisibleTodoList />
<Footer />
</div>
);
ReactDOM.render(
<Provider store={createStore(todoApp)}>
<TodoApp />
</Provider>,
document.getElementById('root')
);
</script>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment