我在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
,它可以正常说话。有问题?
答案 0 :(得分:63)
initialState
中的createStore()
参数经常使人绊倒。它绝不是一种手动“初始化”应用程序状态的方法。唯一有用的应用是:
暗示您永远不会手动编写initialState
,而在大多数应用中,您甚至都不会使用它。相反,reducers必须始终指定自己的初始状态,而initialState
只是在您拥有该状态的现有序列化版本时预填充该状态的方法。
所以this answer是正确的:您需要来定义reducer中的初始状态。将它提供给createStore()
是不够的,并不意味着在代码中定义初始状态。
答案 1 :(得分:28)
我有同样的错误,但我没有包含默认案例
function generate(state={} ,action) {
switch (action.type) {
case randomNumber:
return {
...state,
random: action.payload
}
default: // need this for default case
return state
}
}
答案 2 :(得分:23)
第一次调用reducers时,状态未定义。然后,您必须返回初始状态(错误消息告诉您的内容)。 定义初始状态值的常用方法是为state参数设置默认值:
function postsBySubreddit(state = {}, action) {}
posts
函数中有初始状态,但在初始化期间未调用。
答案 3 :(得分:8)
另外,请确保在reducer中最后返回默认状态。有时您可能忘记确保这是switch语句的默认设置(在重构和移动代码时)。
...
default:
return state
答案 4 :(得分:4)
我只是碰到了同样的障碍,因为我意外地在我的reducer中重新定义了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;
答案 5 :(得分:4)
根据redux文档:https://redux.js.org/basics/reducers
您需要在开关功能之外返回状态 像这样:
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
}
答案 6 :(得分:1)
确保你在最后有一个默认状态
...
default:
return state;
答案 7 :(得分:0)
请确保:
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
。
您可以通过检查以下位置来调试它:
undefined
。答案 8 :(得分:0)
就我而言,我使用的是 React + 打字稿,所以我遇到了这个错误
<块引用>"如果传递给reducer的state是undefined,则必须显式返回初始>state。初始状态可能不是undefined。如果不想为这个>reducer设置值,可以使用null而不是未定义。”
问题是我的减速器是这样的(我会简化它):
export const authReducer = (state : {}, action: ActionType) => {}
应该是
export const authReducer = (state = {}, action: ActionType) => {}
答案 9 :(得分:-1)
export const authReducer = (state = {}, action: ActionType) => {}
不要在状态之后放置':',这会导致错误,而是在 authReducer 的参数中初始化状态后放置 '=' 等号