尽管向createStore()提供了初始状态,为什么我仍然得到“初始化期间返回未定义的Reducer […]”的信息?


69

我已经在redux createStore方法中设置了InitialState,并将对应的InitialState作为第二个参数

我在浏览器中遇到错误:

<code>Uncaught Error: Reducer "postsBySubreddit" returned undefined during initialization. If the state passed to the reducer is undefined, you must explicitly return the initial state. The initial state may not be undefined.</code>

代码在这里:

import { createStore, applyMiddleware } from 'redux'
import thunkMiddleware from 'redux-thunk'
import createLogger from 'redux-logger'
import rootReducer from '../reducers/reducers'
import Immutable from 'immutable'
const loggerMiddleware = createLogger()
//const initialState=0
function configureStore() {
    return createStore(
    rootReducer,
     {postsBySubreddit:{},selectedSubreddit:'reactjs'},
     applyMiddleware(
     thunkMiddleware,
    loggerMiddleware
  )
 )
}
  export default configureStore

我在中调用了configeStore方法Root.js

 import React, { Component } from 'react'
 import { Provider } from 'react-redux'
 import configureStore from '../store/configureStore'
 import AsyncApp from './AsyncApp'
 import Immutable from 'immutable'
 const store = configureStore()
 console.log(store.getState())
 export default class Root extends Component {
 render() {
   return (
     <Provider store={store}>
       <AsyncApp />
     </Provider>
  )
 }
}

但是我猜这initateState有问题:

import { combineReducers } from 'redux'
import {reducerCreator} from '../utils/creator'
import Immutable from'immutable'
import {SELECT_SUBREDDIT, INVALIDATE_SUBREDDIT ,REQUEST_POSTS, RECEIVE_POSTS} from '../actions/action'
let initialState=Immutable.fromJS({isFetching: false, didInvalidate: false,items:[]})

function selectedSubreddit(state, action) {
  switch (action.type) {
  case SELECT_SUBREDDIT:
    return action.subreddit
  default:
    return state
  }
}
function postsBySubreddit(state, action) {
  switch (action.type) {
    case INVALIDATE_SUBREDDIT:
    case RECEIVE_POSTS:
    case REQUEST_POSTS:
      return Object.assign({}, state, {
        [action.subreddit]: posts(state[action.subreddit], action)
      })
    default:
      return state
  }
}
function posts(state=initialState,action) {
  switch (action.type) {
    case INVALIDATE_SUBREDDIT:
      return state.merge({
        didInvalidate: true
      })
    case REQUEST_POSTS:
      return state.merge({
        isFetching: true,
        didInvalidate: false
      })
    case RECEIVE_POSTS:
      return state.merge({
        isFetching: false,
        didInvalidate: false,
        items: action.posts,
        lastUpdated: action.receivedAt
      })
    default:
      return state 
    }
}

const rootReducer = combineReducers({
  postsBySubreddit,
 selectedSubreddit
})
export default rootReducer

但是,如果我initialState在每个子减速器中都设置了字词,则可以正常显示。有问题?

Answers:


81

initialState在辩论中createStore()经常跳闸的人。绝不是要手动“初始化”应用程序状态的方法。唯一有用的应用程序是:

  • 从JSON状态有效负载启动服务器呈现的应用程序。
  • 从保存到本地存储的状态“恢复”应用程序。

这意味着您从不initialState手动编写,在大多数应用程序中甚至都不使用它。取而代之的是,reduce必须始终指定其自己的初始状态,并且这initialState是在具有现有序列化版本时预填充该状态的一种方式。

因此,此答案是正确的:您需要在减速器中定义初始状态。将其提供给用户createStore()是不够的,也不意味着是在代码中定义初始状态的一种方法。


9
这似乎与Redux文档中的描述相矛盾:redux.js.org/docs/recipes/reducers/InitializingState.html
马丁

1
从终极版的文档All reducers are passed undefined on initialization, so they should be written such that when given undefined
AKS

66

我有同样的错误,但没有包括默认情况

function generate(state={} ,action) {
  switch (action.type) {
    case randomNumber:
      return {
        ...state,
        random: action.payload
      }   
    default: // need this for default case
      return state 
   }
}

8
是! 这是我的问题。
罗布·格兰特

1
通常Eslint或Prettier会发现我没有默认情况。所以谢谢!这很容易被忽略。
卡尔·泰勒

1
是的,我也忘记添加默认大小写。谢谢。
艾伦·姆西西瓦

1
我回来了,是的,它又解决了。我应该停止忘记事情。
罗布·格兰特

1
这也是我的问题。
iaq '20

32

另外,请确保在减速器中最后一次返回默认状态。有时您会忘记确保这是switch语句的默认设置(重构和移动代码时)。

...
 default:
  return state

2
谢谢!这绝对是救生员。说的还不够。
anon58192932 '19

2
没问题!使用我自己的复制面食(即redux动作)时,我什至针对相同的问题回答了同样的问题;)
TechnoTim19年

29

初次调用reducer时,状态是不确定的。然后,您必须返回初始状态(这就是错误消息告诉您的内容)。定义初始状态值的通常方法是为state参数设置默认值:

function postsBySubreddit(state = {}, action) {}

您在posts函数中具有初始状态,但是在初始化期间不会调用它。


但我在第二个参数的createStore方法中有一个初始状态
Ice Wilder

你是对的。看起来其中一个键与reducer不匹配:selectedsubreddit => selectedSubreddit。可能是错误的根源吗?
Florian Cargoet

早上它可以正常运行,但是今天下午它无法正常工作,并且浏览器也显示相同的错误。我从不更改代码,但仍然显示相同的错误
Ice Wilder

7

我刚刚遇到了同样的问题,因为我不小心state在减速器中重新定义了:

const initialState = {
  previous: true,
  later: true
}

const useTypeReducer = (state = initialState, action) => {
  switch (action.type) {
    case 'TOGGLE_USE_TYPES':
      let state = Object.assign({}, state);   // DON'T REDEFINE STATE LIKE THIS!
      state[action.use] = !state[action.use];
      return state;

    default:
      return state;
  }
}

export default useTypeReducer;

要解决此问题,我需要避免重新定义状态:

const initialState = {
  previous: true,
  later: true
}

const useTypeReducer = (state = initialState, action) => {
  switch (action.type) {
    case 'TOGGLE_USE_TYPES':
      let _state = Object.assign({}, state);   // BETTER
      _state[action.use] = !state[action.use];
      return _state;

    default:
      return state;
  }
}

export default useTypeReducer;

4

根据redux的文档: https

您需要像这样将状态返回到开关功能之外:


 function posts(state=initialState,action) {
  switch (action.type) {
    case INVALIDATE_SUBREDDIT:
      return state.merge({
        didInvalidate: true
      })
    case REQUEST_POSTS:
      return state.merge({
        isFetching: true,
        didInvalidate: false
      })
    case RECEIVE_POSTS:
      return state.merge({
        isFetching: false,
        didInvalidate: false,
        items: action.posts,
        lastUpdated: action.receivedAt
      })
    default:
      return state 
    }

//here you should put the return state
return state
}

如果我们在switch语句外返回状态,则该状态将变得不可访问
詹姆斯

嗯,我正在遵循文档。它可能现在已更新。谢谢您的注意
Khorram Bin Salim Khondkar

0

tl; dr

确保:

  • 您实际上是通过动作/动作创建者将数据传递给减速器的!
  • 减速机不返回undefined

const reducer = (state = initialState, action) => {
  switch (action.type) {
    case 'SET_DATA':
      debugger // Place a breakpoint for investigation
      const result = update(state, {$set: action.data});
      // `result` is `undefined` if `action.data` is too
      return result;
    default:
      return state;
  }
}

在这种情况下,如果您不小心通过操作创建者传递了代码undefinedaction.data那么react-addons-update将返回undefined来自该变量的。由于这会覆盖整个reducer状态,因此它将返回undefined将触发错误的状态。

调试

您可以通过检查以下位置来调试它:

  • 减速器创建新状态的位置。在该部分放置一个断点,以确保您没有收到或返回undefined那里。
  • 数据传递到动作创建者的位置。
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.