Почему я получаю "Редуктор [...] возвращен undefined во время инициализации", несмотря на предоставление initialState для createStore()?
Я установил InitialState в моем методе createStore redux, и я соответствую 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
в моем суборедукторе, он может нормально делать слово. Что-то не так?
Ответы
Ответ 1
Аргумент initialState
в createStore()
часто отключает людей. Это никогда не означало способ "инициализировать" состояние вашего приложения вручную. Единственными полезными приложениями для него являются:
- Загрузка загруженного сервера из приложения JSON.
- "Возобновление" приложения из состояния, сохраненного в локальном хранилище.
Предполагается, что вы никогда не пишете initialState
вручную, а в большинстве приложений вы даже не используете его. Вместо этого редукторы должны всегда указывать свое собственное начальное состояние, а initialState
- это просто способ заполнить это состояние, когда у вас есть существующая сериализованная версия.
Итак этот ответ правильный: вам нужен, чтобы определить начальное состояние в вашем редукторе. Поставить его в createStore()
недостаточно, и он не предназначен для определения исходного состояния в коде.
Ответ 2
Когда ваши редукторы вызываются в первый раз, состояние undefined. Затем вы должны вернуть исходное состояние (это сообщение об ошибке).
Обычный способ определения начального значения состояния - установить значение по умолчанию для параметра состояния:
function postsBySubreddit(state = {}, action) {}
У вас есть начальное состояние в функции posts
, но оно не вызывается во время инициализации.
Ответ 3
У меня была такая же ошибка, но я не включил случай по умолчанию
function generate(state={} ,action) {
switch (action.type) {
case randomNumber:
return {
...state,
random: action.payload
}
default: // need this for default case
return state
}
}
Ответ 4
Кроме того, убедитесь, что вы возвращаете состояние по умолчанию в редукторе. Иногда вы можете забыть убедиться, что это значение по умолчанию для оператора switch (при рефакторинге и перемещении кода).
...
default:
return state
Ответ 5
Я просто попал в ту же самую зацепку, потому что я случайно переопределил состояние внутри моего редуктора:
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;