Skip to content

Instantly share code, notes, and snippets.

@AleStranieri
Last active March 17, 2018 10:24
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 AleStranieri/5e50c7b5c83e7c9b02667cc23c4f0cdd to your computer and use it in GitHub Desktop.
Save AleStranieri/5e50c7b5c83e7c9b02667cc23c4f0cdd to your computer and use it in GitHub Desktop.
Redux Tutorial - Todo List
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<title>JS Bin</title>
<script src="https://unpkg.com/babel-standalone@6/babel.min.js"></script>
<script crossorigin src="https://cdnjs.cloudflare.com/ajax/libs/redux/3.7.2/redux.js"></script>
<script crossorigin src="https://unpkg.com/react@16/umd/react.development.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script>
</head>
<body>
<div id='root'></div>
<script type="text/babel">
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) => {
switch (action.type) {
case 'ADD_TODO':
return [
...state,
todo(undefined, action)
];
case 'TOGGLE_TODO':
return state.map(t => todo(t, action));
default:
return state;
}
};
const visibilityFilter = (
state= 'SHOW_ALL',
action
) => {
switch (action.type) {
case 'SET_VISIBILITY_FILTER':
return action.filter;
default:
return state;
}
}
const { combineReducers } = Redux;
const todoApp = combineReducers({
todos,
visibilityFilter
});
const { createStore } = Redux;
const store = createStore(todoApp);
const { Component } = React;
const FilterLink = ({
filter,
currentFilter,
children,
onClick
}) => {
if (filter === currentFilter) {
return (<span>{children}</span>);
}
return (
<a href='#'
onClick={e => {
e.preventDefault();
onClick(filter);
}}>
{children}
</a>
);
};
const Footer = ({
visibilityFilter,
onFilterClick
}) => (
<p>
Show:
{' '}
<FilterLink
filter='SHOW_ALL'
currentFilter={visibilityFilter}
onClick={onFilterClick}
>
All
</FilterLink>
{' '}
<FilterLink
filter='SHOW_ACTIVE'
currentFilter={visibilityFilter}
onClick={onFilterClick}
>
Active
</FilterLink>
{' '}
<FilterLink
filter='SHOW_COMPLETED'
currentFilter={visibilityFilter}
onClick={onFilterClick}
>
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 AddTodo = ({
onAddClick
}) => {
let input;
return (
<div>
<input ref= {node => {
input = node;
}} />
<button onClick={() => {
onAddClick(input.value);
input.value = '';
}}>
Add Todo
</button>
</div>
);
};
const getVisibleTodos = (
todos,
filter
) => {
switch (filter) {
case 'SHOW_ALL':
return todos;
case 'SHOW_ACTIVE':
return todos.filter(
t => !t.completed
);
case 'SHOW_COMPLETED':
return todos.filter(
t => t.completed
);
}
}
let nextTodoId = 0;
const TodoApp = ({
todos,
visibilityFilter
}) => (
<div>
<AddTodo
onAddClick={ text =>
store.dispatch({
type: 'ADD_TODO',
text,
id: nextTodoId++
})
}
/>
<TodoList
todos={
getVisibleTodos(
todos,
visibilityFilter
)
}
onTodoClick={id =>
store.dispatch({
type: 'TOGGLE_TODO',
id
})
} />
<Footer
visibilityFilter={visibilityFilter}
onFilterClick={filter =>
store.dispatch({
type:'SET_VISIBILITY_FILTER',
filter
})
}
/>
</div>
);
const render = () => {
ReactDOM.render(
<TodoApp
{...store.getState()}
/>,
document.getElementById('root')
);
};
store.subscribe(render);
render();
</script>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment