Skip to content

Instantly share code, notes, and snippets.

@ghigt
Created July 4, 2016 15:43
Show Gist options
  • Save ghigt/0deb97aa0cd8ffe5ddc1209fb7df82a7 to your computer and use it in GitHub Desktop.
Save ghigt/0deb97aa0cd8ffe5ddc1209fb7df82a7 to your computer and use it in GitHub Desktop.
/*
* 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