[Redux] React Todo List Example (Toggling a Todo)

/**
 * A reducer for a single todo
 * @param state
 * @param action
 * @returns {*}
 */
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;
    }
};

/**
 * The reducer for the todos
 * @param state
 * @param action
 * @returns {*}
 */
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;

    }
};

/**
 * Reducer for the visibilityFilter
 * @param state
 * @param action
 * @returns {*}
 */
const visibilityFilter = ( state = 'SHOW_ALL',
                           action ) => {
    switch ( action.type ) {
        case 'SET_VISIBILITY_FILTER':
            return action.filter;
        default:
            return state;
    }
};

/**
 * combineReducers: used for merge reducers togethger
 * createStore: create a redux store
 */
const { combineReducers, createStore } = Redux;
const todoApp = combineReducers( {
    todos,
    visibilityFilter
} );

const store = createStore( todoApp );

/**
 * For generate todo's id
 * @type {number}
 */
let nextTodoId = 0;

/**
 * React related
 */
const {Component} = React;
class TodoApp extends Component {
    render() {
        return (
            <div>
                <input ref={
        (node)=>{
            this.input = node
        }
    }/>
                <button onClick={
        ()=>{
        //After clicking the button, dispatch a add todo action
            store.dispatch({
                type: 'ADD_TODO',
                id: nextTodoId++,
                text: this.input.value
            })
            this.input.value = "";
        }
    }>ADD todo
                </button>
                <ul>
                    //loop thought the todo list
                    {this.props.todos.map( ( todo )=> {
                        return (
                            <li key={todo.id}
                                style={{
                                 textDecoration: todo.completed ?
                                 'line-through' : 'none'
                                }}

                                onClick={ ()=>{
                                   store.dispatch({
                                   type: 'TOGGLE_TODO',
                                   id: todo.id
                                  })
                                }}
                            >
                                {todo.text}
                            </li>
                        )
                    } )}
                </ul>
            </div>
        );
    }
}

const render = () => {
    ReactDOM.render(
        <TodoApp todos={store.getState().todos}/>,
        document.getElementById( 'root' )
    );
};

//Every time, store updated, also fire the render() function
store.subscribe( render );
render();

原文地址:https://www.cnblogs.com/Answer1215/p/5125439.html