尽管为createStore()提供了initialState,为什么我在初始化期间得到“Reducer [...]返回未定义”?

时间:2021-07-20 17:59:08

I had set InitialState in my redux createStore method ,and I corresponding InitialState as second arguments

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

I got a error in browser:

我在浏览器中出错:

<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>

code is here:

代码在这里:

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

and I invoked configeStoremethod in Root.js:

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

 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>
  )
 }
}

but I guess this initateState has something wrong:

但我猜这个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

but if I set initialState in my every sub reducer it can did word normally. Something wrong?

但是如果我在我的每个子减速器中设置initialState,它可以正常地执行。有问题?

5 个解决方案

#1


51  

The initialState argument in createStore() is often tripping people. It was never meant as a way to “initialize” your application state manually. The only useful applications for it are:

createStore()中的initialState参数经常使人绊倒。它从来不是一种手动“初始化”应用程序状态的方法。唯一有用的应用是:

  • Booting up server rendered app from JSON state payload.
  • 从JSON状态有效负载启动服务器呈现的应用程序。

  • “Resuming” the app from a state saved into local storage.
  • 从恢复到本地存储的状态“恢复”应用程序。

It is implied that you never write initialState manually and in most apps you don’t even use it. Instead, reducers must always specify their own initial state, and initialState is just a way to prefill that state when you have an existing serialized version of it.

暗示你永远不会手动编写initialState,在大多数应用程序中你甚至都不使用它。相反,reducers必须始终指定自己的初始状态,而initialState只是在您拥有现有序列化版本时预填充该状态的一种方法。

So this answer is correct: you need to define the initial state in your reducer. Supplying it to createStore() is not enough, and is not meant to be a way to define the initial state in code.

所以这个答案是正确的:您需要在reducer中定义初始状态。将它提供给createStore()是不够的,并不意味着在代码中定义初始状态。

#2


20  

I had the same error but I didn't include a default case

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

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

#3


19  

When your reducers are called for the first time, state is undefined. You must then return the initial state (that's what the error message is telling you). The usual way of defining the initial state value is to set a default value for the state parameter:

当您的Reducer第一次被调用时,状态是未定义的。然后,您必须返回初始状态(这是错误消息告诉您的)。定义初始状态值的常用方法是为state参数设置默认值:

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

You have an initial state in the posts function but it is not called during initialization.

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

#4


6  

Also, make sure that you are returning the default state last in your reducer. Sometimes you can forget to make sure this is the default for your switch statement (when refactoring and moving around code).

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

...
 default:
  return state

#5


2  

I just hit this same snag because I accidentally redefined state inside my reducer:

我只是碰到了同样的障碍,因为我意外地重新定义了我的reducer中的状态:

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;

To fix the problem I needed to refrain from redefining state:

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

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;

#1


51  

The initialState argument in createStore() is often tripping people. It was never meant as a way to “initialize” your application state manually. The only useful applications for it are:

createStore()中的initialState参数经常使人绊倒。它从来不是一种手动“初始化”应用程序状态的方法。唯一有用的应用是:

  • Booting up server rendered app from JSON state payload.
  • 从JSON状态有效负载启动服务器呈现的应用程序。

  • “Resuming” the app from a state saved into local storage.
  • 从恢复到本地存储的状态“恢复”应用程序。

It is implied that you never write initialState manually and in most apps you don’t even use it. Instead, reducers must always specify their own initial state, and initialState is just a way to prefill that state when you have an existing serialized version of it.

暗示你永远不会手动编写initialState,在大多数应用程序中你甚至都不使用它。相反,reducers必须始终指定自己的初始状态,而initialState只是在您拥有现有序列化版本时预填充该状态的一种方法。

So this answer is correct: you need to define the initial state in your reducer. Supplying it to createStore() is not enough, and is not meant to be a way to define the initial state in code.

所以这个答案是正确的:您需要在reducer中定义初始状态。将它提供给createStore()是不够的,并不意味着在代码中定义初始状态。

#2


20  

I had the same error but I didn't include a default case

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

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

#3


19  

When your reducers are called for the first time, state is undefined. You must then return the initial state (that's what the error message is telling you). The usual way of defining the initial state value is to set a default value for the state parameter:

当您的Reducer第一次被调用时,状态是未定义的。然后,您必须返回初始状态(这是错误消息告诉您的)。定义初始状态值的常用方法是为state参数设置默认值:

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

You have an initial state in the posts function but it is not called during initialization.

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

#4


6  

Also, make sure that you are returning the default state last in your reducer. Sometimes you can forget to make sure this is the default for your switch statement (when refactoring and moving around code).

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

...
 default:
  return state

#5


2  

I just hit this same snag because I accidentally redefined state inside my reducer:

我只是碰到了同样的障碍,因为我意外地重新定义了我的reducer中的状态:

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;

To fix the problem I needed to refrain from redefining state:

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

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;