使用CombineReducer后无法访问props

使用CombineReducer后无法访问props

本文介绍了使用CombineReducer后无法访问props的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我之前的 React-Redux 实现是有效的,但是在我尝试使用单独的文件实现 combineReducer 函数之后,抛出了一个我不太理解的错误.希望你们中的一些人可以帮助我!

错误:未捕获的类型错误:this.props.todos.map 不是函数

我对该代码的参考是 Redux-Doc 的异步示例.但是我用另一个例子说明了每个例子的变化都没有记录在文档中.

我将展示的第一个代码是我有(工作):

我的商店

import { createStore, applyMiddleware } from 'redux'从redux-thunk"导入 thunkMiddleware从redux-logger"导入 createLogger从 '../reducers/addItem' 导入 addItem导出默认函数 configureStore(preloadedState) {const store = createStore(新增项目,预加载状态,应用中间件(thunkMiddleware,createLogger()))如果(模块.热){//为 reducer 启用 Webpack 热模块替换module.hot.accept('../reducers', () => {const nextRootReducer = require('../reducers').defaultstore.replaceReducer(nextRootReducer)})}退货商店}

我的减速机

export default (state = ['Test'], action) =>{开关(动作.类型){案例ADD_ITEM"://返回action.item返回 [...状态,{id:action.id,文本:action.item}]默认:返回状态}}

动作

导出默认函数 addItem(item){console.log("addTOdo")返回 {类型:'ADD_ITEM',id: nextTodoId++,物品}}

以及最终渲染输入的子组件

 import React, { Component, PropTypes } from 'react'从'react-redux'导入{连接}导出默认类 TodoList 扩展组件 {使成为() {const 帖子 = this.propsconst isEmpty = posts.length === 0返回 (<div><h3>Meine Aufgaben</h3><ul>{是空的?<h3>Sie haben noch keinen Todo´s angelegt</h3>:<h3>Ihre Ergebnisse</h3>}{this.props.todos.map((todo, i) => <li key={i}>{todo.text} </li>)}

)}}const mapStateToProp = state =>({待办事项:状态})导出默认连接(mapStateToProp)(TodoList)

我有什么变化:

首先,我创建了另一个名为 Index 的 Reducers 文件,我在其中导入了 addItem Reducer 并导出了 rootReducer:

从'redux'导入{combineReducers}从 './addItem' 导入 addItem从 './getItem' 导入 getItemconst rootReducer = combineReducers({新增项目,获取项目})导出默认 rootReducer

之后,我更改了 Store 以导入 rootReducer 并将其引用放入 Store(只是对 configureStore 的更改):

从'../reducers/index'导入rootReducerconst store = createStore(根减速器,预加载状态,应用中间件(thunkMiddleware,createLogger()))

我不知道是否也需要该信息,但这是我的容器组件:

import React, { Component, PropTypes } from 'react'从'../components/AddTodo' 导入 AddTodo从 '../components/TodoList' 导入 TodoList从'react-redux'导入{连接}从 '../actions/addItem' 导入 addItem从'../actions/getItems'导入getItems类 App 扩展组件 {构造函数(道具){超级(道具)this.handleClick = this.handleClick.bind(this)this.state = {文本:''}}句柄点击(e){控制台日志(e);const {dispatch} = this.props调度(添加项目(e));}componentDidMount(){console.log("组件安装");const {dispatch} = this.props//调度(getItems())}componentWillReceiveProps(nextProps) {console.log("GETTT IT");控制台日志(nextProps)}使成为() {返回 (<div><h1>你好</h1><AddTodo handleAddItem={this.handleClick}/><待办事项列表/>

)}}App.propTypes = {调度:PropTypes.func.isRequired}函数 mapStateToProps(state){返回 {添加待办事项}}导出默认连接 (mapStateToProps)(App)

我希望这个问题不是基本的,有人可以帮助我.提前致谢!

解决方案

如果您检查您的 redux 状态,您将看到以下代码在状态中设置了另外 2 个键(addItemgetItem):

const rootReducer = combineReducers({新增项目,获取项目})

因此,现在要连接 todos,您需要使用 2 个新密钥之一.如果 todos 没有定义在那些上面,那么你需要将 todos 的 reducer 添加到 combineReducers 调用中.

所以这需要映射到状态中的有效位置:

const mapStateToProp = state =>({待办事项:状态})

My previous React-Redux implementation was working, but after I tried to implement the combineReducer function with seperated files, an error is thrown that I don´t really understand. Hope some of you can help me!

ERROR: Uncaught TypeError: this.props.todos.map is not a function

My Reference for that Code was the Async Example of the Redux-Doc´s. But I stated with another example and the change from each examples are not documented in the doc´s.

The first code I will show, is that I had (working):

MyStore

import { createStore, applyMiddleware } from 'redux'
import thunkMiddleware from 'redux-thunk'
import createLogger from 'redux-logger'
import addItem from '../reducers/addItem'

export default function configureStore(preloadedState) {
   const store = createStore(
    addItem,
    preloadedState,
    applyMiddleware(thunkMiddleware, createLogger())
)

if (module.hot) {
    // Enable Webpack hot module replacement for reducers
    module.hot.accept('../reducers', () => {
        const nextRootReducer = require('../reducers').default
        store.replaceReducer(nextRootReducer)
   })
}

    return store
}

My Reducer

export default (state = ['Test'], action) => {
    switch (action.type){
       case 'ADD_ITEM':
        //return action.item
        return [
            ...state,
            {
                id: action.id,
                text: action.item
            }
        ]
    default:
        return state

    }
 }

Actions

export default function addItem(item){
   console.log("addTOdo")
   return {
    type: 'ADD_ITEM',
    id: nextTodoId++,
    item
   }
 }

And the subComponent where the input is finally rendered

 import React, { Component, PropTypes } from 'react'
 import { connect } from 'react-redux'

 export default class TodoList extends Component {

render() {
    const posts = this.props
    const isEmpty = posts.length === 0
    return (

        <div>
            <h3>Meine Aufgaben</h3>
            <ul>
                {isEmpty
                    ? <h3>Sie haben noch keinen Todo´s angelegt</h3>
                    : <h3>Ihre Ergebnisse</h3>
                }
                {this.props.todos.map((todo, i) => <li key={i}>{todo.text}       </li>)}
            </ul>
        </div>
        )
      }
  }
  const mapStateToProp = state => ({todos: state})

  export default connect (mapStateToProp)(TodoList)

What I have change:

First, I created another Reducers File, called Index where I imported the addItem Reducer and exported the rootReducer:

import {combineReducers} from 'redux'
import addItem from './addItem'
import getItem from './getItem'

const rootReducer = combineReducers({
   addItem,
   getItem
 })

 export default rootReducer

After that, I changed the Store to import the rootReducer and put it´s reference in the Store (just the changes to configureStore):

import rootReducer from '../reducers/index'

 const store = createStore(
    rootReducer,
    preloadedState,
    applyMiddleware(thunkMiddleware, createLogger())
)

I don´t know if that Information is also required, but here is my Container Component:

import React, { Component, PropTypes } from 'react'
import AddTodo from '../components/AddTodo'
import TodoList from '../components/TodoList'
import { connect } from 'react-redux'
import addItem from '../actions/addItem'
import getItems from '../actions/getItems'

class App extends Component {
  constructor(props) {
    super(props)
    this.handleClick = this.handleClick.bind(this)
    this.state = {text: ''}
}

handleClick(e){
    console.log(e);
    const {dispatch} = this.props
    dispatch(addItem(e));
}

componentDidMount(){
    console.log("COMPONENT MOUNT");
    const {dispatch} = this.props
  //  dispatch(getItems())
}

componentWillReceiveProps(nextProps) {
    console.log("GETTT IT");
    console.log(nextProps)
}

render() {

    return (
        <div>
        < h1 > Hallo </h1>
            <AddTodo handleAddItem={this.handleClick}/>
            <TodoList/>
        </div>
    )
  }
}

App.propTypes = {
    dispatch: PropTypes.func.isRequired
}

function mapStateToProps(state){
  return {
    AddTodo
 }
}

export default connect (mapStateToProps)(App)

I hope this issue is not to basic and someone can help me. Thanks in advance!

解决方案

If you inspect your redux state you will see that the following code sets up 2 more keys in the state (addItem and getItem):

const rootReducer = combineReducers({
   addItem,
   getItem
 })

So, now to connect todos you need to one of the 2 new keys. If todos is not defined on those, then you need to add the reducer of todos to the combineReducers call.

So this needs to map to a valid location in state:

const mapStateToProp = state => ({todos: state})

这篇关于使用CombineReducer后无法访问props的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

09-05 06:25