Redux createStoreメソッドにInitialStateを設定し、対応するInitialStateを2番目の引数として設定しました
ブラウザでエラーが発生しました:
<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
Root.js
でconfigeStore
methodを呼び出しました:
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
を設定すると、通常どおりWordを実行できます。何か問題でも?
createStore()
のinitialState
引数は、しばしば人をつまずかせます。アプリケーションの状態を手動で「初期化」する方法として意図されたものではありません。唯一の有用なアプリケーションは次のとおりです。
initialState
を手動で記述しないでください。ほとんどのアプリでは使用しません。代わりに、リデューサーは常に独自の初期状態を指定する必要があり、initialState
は、既存のシリアル化されたバージョンがある場合にその状態を事前に入力する方法にすぎません。
この答え は正しい:あなたneedは、レデューサーの初期状態を定義する。 createStore()
に指定するだけでは不十分であり、コードで初期状態を定義する方法を意図したものではありません。
同じエラーが発生したが、デフォルトのケースを含めなかった
function generate(state={} ,action) {
switch (action.type) {
case randomNumber:
return {
...state,
random: action.payload
}
default: // need this for default case
return state
}
}
レデューサーが初めて呼び出されたとき、状態は未定義です。その後、初期状態を返す必要があります(これがエラーメッセージに示されています)。初期状態値を定義する通常の方法は、状態パラメーターのデフォルト値を設定することです。
function postsBySubreddit(state = {}, action) {}
posts
関数に初期状態がありますが、初期化中には呼び出されません。
また、リデューサーで最後にデフォルトの状態を返すようにしてください。これがswitchステートメントのデフォルトであることを忘れることがあります(コードのリファクタリングおよび移動時)。
...
default:
return state
レデューサー内で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;
以下を確認してください。
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
を返します。これはレデューサーの状態全体を上書きするため、エラーをトリガーするundefined
を返します。
これをデバッグするには、次の場所を調べます。
undefined
が届かないことを確認します。