93 votes

Pourquoi est-ce que j'obtiens "Reducer [...] returned undefined during initialization" alors que j'ai fourni initialState à createStore() ?

J'avais défini InitialState dans ma méthode redux createStore ,et j'ai correspondant InitialState comme second argument

J'ai une erreur dans le navigateur :

<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>

Le code est ici :

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

et j'ai invoqué configeStore méthode dans 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>
  )
 }
}

mais je suppose que initateState a quelque chose qui ne va pas :

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

mais si je mets initialState dans tous mes sous-réducteurs il peut faire le mot normalement. Y a-t-il un problème ?

111voto

Isaac Pak Points 855

J'ai eu la même erreur mais je n'ai pas inclus un cas par défaut

function generate(state={} ,action) {
  switch (action.type) {
    case randomNumber:
      return {
        ...state,
        random: action.payload
      }   
    default: // need this for default case
      return state 
   }
}

8 votes

Oui ! C'était mon problème.

1 votes

D'habitude, Eslint ou Prettier se rendaient compte que je n'avais pas de dossier par défaut. Merci donc ! C'est facilement négligé.

1 votes

Oui, j'ai oublié d'ajouter le cas par défaut aussi. Merci.

95voto

Dan Points 16670

Le site initialState argument dans createStore() fait souvent trébucher les gens. Il n'a jamais été conçu comme un moyen d'"initialiser" manuellement l'état de votre application. Les seules applications utiles sont :

  • Démarrage de l'application rendue par le serveur à partir d'une charge utile d'état JSON.
  • "Reprise" de l'application à partir d'un état sauvegardé dans le stockage local.

Il est sous-entendu que vous n'écrivez jamais initialState manuellement et dans la plupart des applications, vous ne l'utilisez même pas. Au lieu de cela, les reducers doivent toujours spécifier leur propre état initial, et initialState est juste un moyen de pré-remplir cet état lorsque vous avez une version sérialisée existante de celui-ci.

Alors cette réponse est correct : vous necesita pour définir l'état initial dans votre réducteur. En le fournissant à createStore() n'est pas suffisant, et n'est pas censé être un moyen de définir l'état initial dans le code.

12 votes

Cela semble contredire la description de la documentation de Redux : redux.js.org/docs/recipes/reducers/InitializingState.html

2 votes

Extrait de la documentation de redux All reducers are passed undefined on initialization, so they should be written such that when given undefined

0 votes

La réponse de @aks est en fait plus appropriée. J'ai eu un problème similaire mais probablement causé par le même problème. J'ai découvert que les réducteurs sont censés traiter undefined en tant que paramètre et sont supposés retourner l'état initial dans ces cas, selon la documentation redux.

46voto

TechnoTim Points 41

Assurez-vous également que vous renvoyez le état par défaut dernier dans votre réducteur. Parfois, vous pouvez oublier de vous assurer que c'est la valeur par défaut de votre instruction switch (lors du remaniement et du déplacement du code).

...
 default:
  return state

2 votes

MERCI ! Cela m'a sauvé la vie. Je ne le dirai jamais assez.

2 votes

Pas de problème ! J'ai même atterri sur cette même réponse pour le même problème en utilisant mes propres pâtes à copier que sont les actions redux ;)

33voto

Florian Cargoet Points 419

Lorsque vos réducteurs sont appelés pour la première fois, l'état est indéfini. Vous devez alors retourner l'état initial (c'est ce que vous dit le message d'erreur). La façon habituelle de définir la valeur de l'état initial est de définir une valeur par défaut pour le paramètre state :

function postsBySubreddit(state = {}, action) {}

Vous avez un état initial dans le posts mais elle n'est pas appelée pendant l'initialisation.

0 votes

Mais j'ai un état initial dans la méthode createStore sur les seconds arguments

0 votes

Vous avez raison. Il semble que l'une des clés ne corresponde pas au réducteur : selectedsubreddit => selectedSubreddit. Cela pourrait-il être la source de l'erreur ?

0 votes

Le matin, il fonctionne correctement, mais cet après-midi, il ne fonctionne pas et le navigateur affiche la même erreur. Je n'ai jamais changé mon code mais il montre toujours la même erreur.

9voto

duhaime Points 494

Je viens de rencontrer le même problème parce que j'ai accidentellement redéfini state dans mon réducteur :

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;

Pour résoudre le problème, je devais m'abstenir de redéfinir l'État :

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;

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X