【问题标题】:Redux/React. After implement the combineReducers cannot get state of app还原/反应。实施后 combineReducers 无法获取应用程序的状态
【发布时间】:2018-04-02 15:55:43
【问题描述】:

将两个reducers 组合在一起(EditButtonTodoApp)后,我的应用程序每次都开始崩溃。在此之前,当我只使用一个减速器TodoApp 时,reducers 没有任何问题。但是现在我无法弄清楚出了什么问题,因为每次我在下面的componentmap 函数中得到错误。错误“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})

/* 应用程序 */

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;

/* 容器 */

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)

/* 组件 */

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;

【问题讨论】:

    标签: reactjs redux react-redux


    【解决方案1】:

    当您在 combineReducers 中使用 ES6 属性简写符号时:

    combineReducers({TodoApp, EditButton})

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

    但是在您的 CONTAINER 中,您正在访问 state.todos,没有来自状态的名为 todos 的东西,而是来自它的 TodoApp,因此您在 .map() 中得到 错误

    this.props.todos.map((iteam, index) {} 
    

    编辑: 当您从您的 reducer 返回一个包含数组的对象时,称为 todos,因此要访问正确的状态,您需要使用 reducer Name 后跟要返回的数组名称,即 TodoApp.todos

    所以在你的容器内你需要访问正确的reducer

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

    您可以在Redux Documentation 上阅读有关 combineReducers 的更多信息

    【讨论】:

    • 谢谢,但这是行不通的。如上所示,我更改了容器。但什么也没有发生。此外,我第二次尝试更改组件中的todos,如this.props.TodoApp.map((iteam, index) =&gt;,但也没有结果......我还看到了Redux官方文档,但他们只说直接使用combineReducer状态,而不是真正的应用程序
    • 在上面的代码中,我看不到您将任何props 传递给您的COMPONENT,这个this.props.todos 来自哪里?
    • 它来自上面的container - const mapStateToProps = state =&gt; ({ todos: state.todos });
    • 哦,我明白是什么问题了。你给我一个很好的目标。我们只需要升级您的解决方案并制作待办事项:state.TodoApp.todos, insted of todos: state.TodoApp。我不明白为什么,但它工作。如果你能理解我,我会很高兴)
    猜你喜欢
    • 1970-01-01
    • 2020-02-01
    • 2018-04-22
    • 2018-06-02
    • 1970-01-01
    • 2019-12-03
    • 1970-01-01
    • 2014-08-30
    • 1970-01-01
    相关资源
    最近更新 更多