Подтвердить что ты не робот

Почему я получаю "Редуктор [...] возвращен 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 в моем суборедукторе, он может нормально делать слово. Что-то не так?

4b9b3361

Ответ 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;