尽管向 createStore() 提供了 initialState,为啥我得到“Reducer [...] 在初始化期间返回未定义”?
Posted
技术标签:
【中文标题】尽管向 createStore() 提供了 initialState,为啥我得到“Reducer [...] 在初始化期间返回未定义”?【英文标题】:Why do I get “Reducer [...] returned undefined during initialization” despite providing initialState to createStore()?尽管向 createStore() 提供了 initialState,为什么我得到“Reducer [...] 在初始化期间返回未定义”? 【发布时间】:2016-08-05 18:29:42 【问题描述】:我在我的 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
我在Root.js
中调用了configeStore
method:
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
,它可以正常运行。有问题?
【问题讨论】:
【参考方案1】:createStore()
中的 initialState
参数经常让人绊倒。它从来都不是一种手动“初始化”应用程序状态的方法。它唯一有用的应用是:
这意味着您永远不会手动编写initialState
,并且在大多数应用程序中您甚至都不使用它。相反,reducer 必须始终指定自己的初始状态,initialState
只是在您拥有现有序列化版本时预填充该状态的一种方式。
所以this answer 是正确的:你需要在你的reducer 中定义初始状态。将其提供给 createStore()
是不够的,也不是在代码中定义初始状态的一种方式。
【讨论】:
这似乎与 Redux 文档中的描述相矛盾:redux.js.org/docs/recipes/reducers/InitializingState.html 来自 redux 文档All reducers are passed undefined on initialization, so they should be written such that when given undefined
@aks 的回答其实更合适。我有一个类似的问题,但可能是由同样的问题引起的。我发现,根据 redux 文档,reducers 应该将 undefined
状态作为参数处理,并且应该在这些情况下返回初始状态。【参考方案2】:
我遇到了同样的错误,但我没有包含默认情况
function generate(state= ,action)
switch (action.type)
case randomNumber:
return
...state,
random: action.payload
default: // need this for default case
return state
【讨论】:
是的!这是我的问题。 通常 Eslint 或 Prettier 会接受我没有默认案例的事实。所以谢谢!这很容易被忽视。 是的,我也忘了添加默认情况。谢谢。 我回来了,是的,它又解决了。我应该停止忘记事情。 这也是我的问题。【参考方案3】:另外,请确保您在 reducer 中最后返回 默认状态。有时您可能会忘记确保这是您的 switch 语句的默认值(在重构和移动代码时)。
...
default:
return state
【讨论】:
谢谢!这绝对是救命稻草。说的不够。 没问题!当使用我自己的复制意大利面时,我什至针对相同的问题得到了相同的答案,即 redux 操作;)【参考方案4】:当你的 reducer 第一次被调用时,状态是未定义的。然后您必须返回初始状态(这就是错误消息告诉您的内容)。 定义初始状态值的常用方法是为状态参数设置一个默认值:
function postsBySubreddit(state = , action)
posts
函数中有一个初始状态,但在初始化期间没有调用它。
【讨论】:
但我在第二个参数的 createStore 方法中有一个初始状态 你是对的。看起来其中一个键与减速器不匹配:selectedsubreddit => selectedSubreddit。会不会是错误的根源? 早上运行正常,下午就不行了,浏览器报同样的错误。我从不更改我的代码,但它仍然显示相同的错误【参考方案5】:我刚刚遇到了同样的问题,因为我不小心在减速器中重新定义了 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;
【讨论】:
【参考方案6】:根据redux的文档:https://redux.js.org/basics/reducers
你需要在 switch 函数之外返回状态 像这样:
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 语句之外返回状态,它将变得无法访问 嗯,我在关注文档。现在应该更新了。感谢您的关注【参考方案7】:确保你在最后有一个默认状态
...
default:
return state;
【讨论】:
【参考方案8】:tl;博士
确保:
您实际上是通过动作/动作创建器将数据传递给减速器! reducer 不返回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;
在这种情况下,如果您不小心通过动作创建器将undefined
传递给action.data
,那么react-addons-update 将返回来自该变量的undefined
。由于这会覆盖整个 reducer 状态,因此它将返回将触发错误的 undefined
。
调试
你可以通过检查这些地方来调试它:
reducer 创建新状态的位置。在该部分放置一个断点,以确保您不会在那里收到或返回undefined
。
数据传递给操作创建者的位置。
【讨论】:
【参考方案9】:对我来说,我有我的减速器
import * as actions from '../actions/budgetActions';
export const initialState =
budget: ,
loading: false,
hasErrors: false,
export default function budgetReducer(state = initialState, action)
switch (action.type)
case actions.GET_BUDGET:
return ...state, loading: true ;
case actions.GET_BUDGET_SUCCESS:
return budget: action.payload, loading: false, hasErrors: false ;
case actions.GET_BUDGET_FAILURE:
return ...state, loading: false, hasErrors: true ;
而不是(我错过了默认情况)
import * as actions from '../actions/budgetActions';
export const initialState =
budget: ,
loading: false,
hasErrors: false,
export default function budgetReducer(state = initialState, action)
switch (action.type)
case actions.GET_BUDGET:
return ...state, loading: true ;
case actions.GET_BUDGET_SUCCESS:
return budget: action.payload, loading: false, hasErrors: false ;
case actions.GET_BUDGET_FAILURE:
return ...state, loading: false, hasErrors: true ;
default:
return state;
【讨论】:
以上是关于尽管向 createStore() 提供了 initialState,为啥我得到“Reducer [...] 在初始化期间返回未定义”?的主要内容,如果未能解决你的问题,请参考以下文章