Why do I get “Reducer […] returned undefined during initialization” despite providing initialState to createStore()?
我已经在我的redux createStore方法中设置了InitialState,并将我对应的InitialState作为第二个参数
浏览器出现错误:
1 | <wyn>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.</wyn> |
代码在这里:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | 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 |
并且我在
中调用了
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | 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> ) } } |
但是我想这个
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 | 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 |
但是如果我在每个子减速器中设置
- 从JSON状态有效负载启动服务器呈现的应用程序。
- 从保存到本地存储的状态"恢复"应用程序。
这意味着您永远不会手动编写
所以这个答案是正确的:您需要在化简器中定义初始状态。将其提供给
我遇到了相同的错误,但是没有包含默认案例
1 2 3 4 5 6 7 8 9 10 11 | function generate(state={} ,action) { switch (action.type) { case randomNumber: return { ...state, random: action.payload } default: // need this for default case return state } } |
此外,请确保您要在减速器中最后返回默认状态。有时您会忘记确保这是switch语句的默认设置(在重构和移动代码时)。
1 2 3 | ... default: return state |
当您的reducers第一次被调用时,状态是不确定的。然后,您必须返回初始状态(这就是错误消息告诉您的内容)。
定义初始状态值的通常方法是为状态参数设置默认值:
1 | function postsBySubreddit(state = {}, action) {} |
您在
我刚刚遇到了同样的问题,因为我不小心在减速器中重新定义了
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | 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; |
要解决此问题,我需要避免重新定义状态:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | 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; |
根据redux的文档:https://redux.js.org/basics/reducers
您需要在开关功能之外返回状态
像这样:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | 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 } |
tl; dr
请确保:
- 您实际上是通过动作/动作创建者将数据传递给减速器的!
-
减速器不返回
undefined 。
例子
1 2 3 4 5 6 7 8 9 10 11 | 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 。 - 数据传递到动作创建者的位置。
在我的情况下,我正在使用Reacttypescript,所以出现了此错误
"If the state passed to the reducer is undefined, you must explicitly return the initial >state. The initial state may not be undefined. If you don't want to set a value for this >reducer, you can use null instead of undefined."
问题是我的减速器是这样的(我会简化它):
1 | export const authReducer = (state : {}, action: ActionType) => {} |
它应该是
1 | export const authReducer = (state = {}, action: ActionType) => {} |