Redux /反应。实施后,CombineReducers无法获取应用程序状态

Max*_*fen 1 reactjs redux react-redux

将两个reducersEditButtonTodoApp)组合在一起后,我的应用每次都崩溃。在此之前,当我仅使用一个减速器时,TodoApp我就没有任何问题reducers。但是现在我无法弄清楚出什么问题了,因为每次我遇到以下map功能时都会出错component。错误“ TypeError:无法读取未定义的属性'map'”。

那么,我忘记了什么?我也无法在的嵌套组件或容器中获取状态App。这也很奇怪,但是例如,App我可以通过console.log()做到这一点。

/ *减速器* /

import { combineReducers } from 'redux'
import { ADD_TODO, EDIT_TODO, DELETE_TODO, FILTER_TODO_UP, FILTER_TODO_DOWN } from '../Variables/Variables'

const initialState = {
    todos: []
}

function EditButton(state, action) {
    if (typeof state === 'undefined') {
        return 'Edit';
    }

    switch (action.type) {
        case EDIT_TODO:
            return state = "Edit" ? "Done" : "Edit"
        default:
            return state
    }
}

function TodoApp(state, action) {
    if (typeof state === 'undefined') {
        return initialState;
    }

    switch (action.type) {
        case ADD_TODO:
            return Object.assign({}, state, {
                todos: [
                    ...state.todos, 
                    {
                        id: action.id,
                        text: action.text,
                        done: action.done
                    }
                ]
            });
        case EDIT_TODO:
            return Object.assign({}, state, {
                todos: [
                    ...state.todos, 
                    {
                        id: action.id,
                        text: action.text,
                        done: action.done
                    }
                ]
            });
        case DELETE_TODO:
            return Object.assign({}, {
                todos: state.todos.filter(todos => todos.id !== parseInt(action.id))
            });
        case FILTER_TODO_UP:
            return Object.assign({}, {
                todos: [
                ...state.todos.sort((a, b) => b.id - a.id)
                ]
            });
        case FILTER_TODO_DOWN:
            return Object.assign({}, {
                todos: [
                    ...state.todos.sort((a, b) => a.id - b.id)
                ]
            });
        default: 
            return state;
    }
}



export default combineReducers({TodoApp, EditButton})
Run Code Online (Sandbox Code Playgroud)

/ * APP * /

import React, { Fragment } from 'react';
import TodoFormAdd from '../Containers/TodoFormAdd';
import TodoListAdd from '../Containers/TodoListAdd';
import TodoFormFilterAdd from '../Containers/TodoFormFilterAdd';

class App extends React.Component {
    constructor(props) {
        super(props);
    }

    render() {
        return(
            <Fragment>
                // console.log(this.props.state.getState()) - work!
                <TodoFormAdd />
                <TodoListAdd store={this.props.store} />
                <TodoFormFilterAdd />
            </Fragment>
        );
    }
}

export default App;
Run Code Online (Sandbox Code Playgroud)

/* 容器 */

import { connect } from 'react-redux';
import TodoList from '../Components/TodoList/TodoList';
import { DeleteTodo } from '../Actions/AddTodo'

// console.log(this.props.state.getState()) - does not work!

const mapStateToProps = state => ({
    todos: state.todos
});

const mapDispatchToProps = dispatch => ({
      todoFormDelete: todo => dispatch(DeleteTodo(todo))
});

export default connect(
    mapStateToProps, 
    mapDispatchToProps)(TodoList)
Run Code Online (Sandbox Code Playgroud)

/* 零件 */

import React from 'react';
import TodoIteam from '../TodoIteam/TodoIteam'

class TodoList extends React.Component {
handleDelete = (e) => {
    let target = e.target;
    let closestDelete = target.closest('span');
    let closestEdit = target.closest('button');

    if (closestDelete) {
        let index = closestDelete.parentNode.getAttribute('index');
        this.props.todoFormDelete(index);
    } else { 
        return 
    }
}

render(props) {
// console.log(this.props.state.getState()) - does not work!

    return (
        <ul onClick={this.handleDelete}>{this.props.todos.map((iteam, index) => 
 // this where I get an error
                <TodoIteam key={index} index={iteam.id} {...iteam} />
            )}
        </ul>
    );
}
}

export default TodoList;
Run Code Online (Sandbox Code Playgroud)

Aaq*_*qib 5

当您在中使用ES6属性速记符号时combineReducers

combineReducers({TodoApp, EditButton})

这相当于写作 combineReducers({ TodoApp: TodoApp, EditButton: EditButton })

但是在您的容器内部,您state.todos没有访问任何todos来自状态的信息,而是来自状态的信息TodoApp,因此您将在以下错误提示.map()

this.props.todos.map((iteam, index) {} 
Run Code Online (Sandbox Code Playgroud)

编辑:当您从调用的reducers返回包含数组的对象时todos,要访问正确的状态,您需要使用reducer Name,然后返回要返回的数组名称,这将是TodoApp.todos

因此,在您的容器内,您需要访问正确的 reducer

const mapStateToProps = state => ({
    todos: state.TodoApp.todos // Notice TodoApp is used instead of todos
});
Run Code Online (Sandbox Code Playgroud)

您可以在Redux文档上阅读有关CombineReducers的更多信息