Redux React Todo List Example

by Allie Yu

HTML

<script src="https://cdnjs.cloudflare.com/ajax/libs/redux/3.5.2/redux.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id="root"></div>

JavaScript

// todo reducer
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 Object.assign({}, state, {
      		completed: !state.completed
	      });
			}
        
			return state;
		default:
    	return state;
  }
};

// todos reducer
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;
  }
};

// visibilityFilter reducer
const visibilityFilter = (
	state = 'SHOW_ALL',
  action
) => {
	switch(action.type) {
  	case 'SET_VISIBILITY_FILTER':
    	return action.filter;
		default:
    	return state;
  }
};

const { combineReducers } = Redux;

// todoApp reducer
const todoApp = combineReducers({
	todos,
  visibilityFilter
});

const { createStore } = Redux;
const store = createStore(todoApp);

const { Component } = React;

const FilterButton = ({
	filter,
  currentFilter,
  children
}) => {
	if (filter === currentFilter) {
  	return React.createElement('span', {}, children);
  }
  
	return React.createElement('button', {
  	type: 'button',
		onClick: (e) => {
    	store.dispatch({
      	type: 'SET_VISIBILITY_FILTER',
				filter
      });
    }
	}, children);
};

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);
  }
};

// TodoApp component
let nextTodoId = 0;
class TodoApp extends Component {
	componentDidMount() {
  	this.input = document.getElementById('input');
  }
	render() {
  	const {
    	todos,
      visibilityFilter
    } = this.props;
  	const visibleTodos = getVisibleTodos(todos,...