Reputation: 8982
I tried simple react,redux,ajax working example and followed Reddit API tutorial, but I cannot create store and get error:
Uncaught Error: Expected the reducer to be a function.
index.jsx
...
import { createStore, applyMiddleware } from 'redux'
var thunkMiddleware = require('redux-thunk');
var createLogger = require('redux-logger');
var rootReducer = require('./reducers.js');
const loggerMiddleware = createLogger();
function configureStore(initialState) {
return createStore(
rootReducer,
initialState,
applyMiddleware(
thunkMiddleware,
loggerMiddleware
)
)
}
const store = configureStore();
...
rootReducer.js
import { combineReducers } from 'redux';
function products(state = {
isFetching: false,
didInvalidate: false,
items: []
}, action) {
switch (action.type) {
case 'REQUEST_PRODUCTS':
return Object.assign({}, state, {
isFetching: true,
didInvalidate: false
})
case 'RECEIVE_PRODUCTS':
return Object.assign({}, state, {
isFetching: false,
didInvalidate: false,
items: action.posts,
lastUpdated: action.receivedAt
})
default:
return state
}
}
function specialPosts(state = { }, action) {
switch (action.type) {
case RECEIVE_SPECPOSTS:
case REQUEST_SPECPOSTS:
return Object.assign({}, state, {
req: true
})
default:
return state
}
}
const rootReducer = combineReducers({
products,
specialPosts
});
export default rootReducer;
Type of rootReducer is object, but why? Should I change createStore
function to rootReducer.default
?
return createStore(
rootReducer.default,
initialState,
applyMiddleware(
thunkMiddleware,
loggerMiddleware
)
)
package.json
"redux-logger": "^2.6.1",
"react-redux": "^4.4.1",
"react-redux-provide": "^5.2.3",
"redux": "^3.3.1",
"redux-thunk": "^2.0.1",
Upvotes: 28
Views: 67963
Reputation: 592
When you see this error: Uncaught Error: Expected the reducer to be a function
, you must make sure that in src/index.js file, the second argument of the createStore()
method must be a function.
This is wrong: const store = createStore(rootReducer, applyMiddleware)
This is ok: const store = createStore(rootReducer, applyMiddleware())
This is ok: const store = configureStore(rootReducer, applyMiddleware())
Upvotes: 0
Reputation: 91
i have faced the same problem and it is solved by
const redux = require('redux');
const store = redux.createStore(reducer);
and my reducer
is
const reducer = (state = initailState, action)=>{
if(action.type === 'BUY_CAKE'){
return {...state, numOfCake : state.numOfCake + 1}
}
if(action.type === BUY_ICECREAM){
return {...state, numOfIceCream : state.numOfIceCream + 1}
}
}
Upvotes: 0
Reputation: 3655
When you see the error:
Uncaught Error: Expected the reducer to be a function
It does not necessarily mean that the reducer
is not a function. If you experience this error, you should try creating the store with just the reducer
. So like this:
createStore(reducer)
Which might be working.
In my case, the second parameter was wrong, because I didn't call compose
and applyMiddleware
in the correct order. So this is a correct setup that seems to have worked in my case:
export const createDebugStore = () => {
const options: EnhancerOptions = {}
const composeFunc = (typeof window !== 'undefined' && composeWithDevTools(options)) || compose;
const enhancer = composeFunc(applyMiddleware());
return createStore((state: any) => state || {}, enhancer);
}
Upvotes: 1
Reputation: 20168
When you create store first argument must be function that means reduce(()=>[]
) parameter
Error:
import {createStore,applyMiddleware} from 'redux';
export default function configureStore(initialState) {
return createStore(
[],
{},
applyMiddleware()
);
}
Solution:
import {createStore,applyMiddleware} from 'redux';
export default function configureStore(initialState) {
return createStore(
()=>[],
{},
applyMiddleware()
);
}
Upvotes: 6
Reputation: 1993
I use VS Code Insiders and sometimes changes are not saved correctly. So if you followed all of the above and the error is still there go to each file and press STRG+S. It solved the issue for me.
Upvotes: 0
Reputation:
/* index.js */
import AppReducer from './reducers';
// import {AppReducer} from './reducers';
// bugs : must be a root reducer, can not be use as a module
/* reducers.js */
// initial state
const initialState = {
angular: 0,
react: 0,
vuejs: 0
};
// reducers update state
const AppReducers = (state = initialState, action) => {
switch (action.type) {
case 'VOTE_ANGULAR':
console.log("Vote Angular!");
return (
Object.assign(
{},
state,
{
angular: state.angular + 1
}
)
);
case 'VOTE_REACT':
console.log("Vote React!");
return (
Object.assign(
{},
state,
{
react: state.react + 1
}
)
);
case 'VOTE_VUEJS':
console.log("Vote Vue.jsc!");
return (
Object.assign(
{},
state,
{
vuejs: state.vuejs + 1
}
)
);
default:
return state;
}
};
export {AppReducers};
export default AppReducers;
Upvotes: 0
Reputation: 1986
The problem was due to rootReducer being imported by "require" (ES5):
var rootReducer = require('./reducers.js');
If you import it via the ES6 method, it will correctly save the rootReducer.js' default automatically into rootReducer as you expected:
import rootReducer from './reducers';
I see you are mixing ES5 (require) and ES6 (import) in that file...I was mixing in my project as well, which is why I ran into this problem. More information can be found here: https://medium.com/@kentcdodds/misunderstanding-es6-modules-upgrading-babel-tears-and-a-solution-ad2d5ab93ce0#.2x2p2dx3m
Upvotes: 9
Reputation: 8180
const rootReducer = combineReducers({
products,
specialPosts
});
const store = createStore( rootReducer, applyMiddleware( thunkMiddleware ));
The initial state is then created automatically from the initial states returned by the individual reducer functions. These individual states can be accessed as state.products
and state.specialPosts
Upvotes: 17