cannot apply multiple middlewares using Redux applyMiddleware function - javascript

Can anyone help me out with the right redux store configuration?
I am trying to configure as follows,
configureStore.js
import thunk from 'redux-thunk';
import logger from 'redux-logger';
import { createStore, applyMiddleware } from 'redux';
import rootReducer from '../reducers';
let middlewares = [thunk, logger]
const configureStore = () => {
const store = createStore(
rootReducer,
applyMiddleware(...middlewares) // I also tried with applyMiddleware(thunk, logger)
);
return store;
}
export default configureStore;
And I import this module main js file and use as follows,
index.js
import configureStore from '../stores/configureStore';
const store = configureStore();
// And other DOM render code follows...
But is seems not working and the following error displays in the web console,
Error: Uncaught TypeError: WEBPACK_IMPORTED_MODULE_0__compose.a.apply(...) is not a function
File in which the error is:
I am following official docs of redux, redux-thunk and redux-logger but unable to make it work.
Another note: It works fine when I remove any one of thunk and logger from the middlewares list.
UPDATE: I got temporary fix
Downgrading redux from 3.7.2 to 3.5.2 works fine.
I still wonder why it is the problem with latest version of Redux. I tried to add more information related to the issue and looking for solution for future upgrades.
Thanks!

You just made a tiny mistake.
From the official docs, here is the signature of createStore:
createStore(reducer, [preloadedState], [enhancer])
You mixed up the order of the arguments, passing your enhancer function (applyMiddleware) where the function is expecting the preloadedState. You need to pass in an argument in between the rootReducer, and the applyMiddleware function, in order to satisfy the signature.
Hope this helped!

Related

Redux - Retrieve data from store and POST it

Newbie at Redux back here again, thanks to the question I posted recently I have been able to use redux-logger to keep track of everything that is updated through the store and knowing that every re-render is being happening at my reducer.
The question is still the same, as now that I can see in my log what is happening and everything is being stored in the store, but how can I retrieve it and post it? I need to post through the API to the backend and do some calculations.
The log of my application https://imgur.com/a/JCPklMV
store.js
import { createStore, applyMiddleware } from 'redux';
import thunk from 'redux-thunk';
import rootReducer from './RootReducer';
export default function configureStore() {
return createStore(
rootReducer,
applyMiddleware(thunk)
);
}
Full code at Sandbox https://codesandbox.io/s/elated-goldberg-1pogb
Thanks in advance!

Unexpected keys, "length", "action", "location" etc in Redux when using connectedRouter

I am trying to write a React app and I am trying to use ConnectedRouter:
https://github.com/supasate/connected-react-router
It's a Redux binding for React Router.
I am getting the following error:
Now I think this is probably related to this question's accepted answer:
Redux: Unexpected key found in preloadedState argument passed to createStore
However unlike there when trying to pass default, I actually probably want these in my combine reducer.
Here's my current code in my reducers/index.js:
export default history =>
combineReducers({
router: connectRouter(history),
search,
profile,
color,
categories,
coordinates: LocationReducer,
idprovider,
firstFavorite,
analytics,
sidebar,
messages,
total_messages,
onesignal,
tokens
});
And in my store.js:
import createRootReducer from "./reducers/index";
I'm not quite sure what the correct solution is here, as ConnectedRouter doesn't seem to do anything with these values.
What is the correct solution?
EDIT: In my example bellow I used syntax used in connected-react-router v4, but my example was definitely wroking.
There was an update in usage for v5/v6, if you are using version>=5, try to migrate my example into it:
https://github.com/supasate/connected-react-router/blob/master/FAQ.md#how-to-migrate-from-v4-to-v5v6
You probably do not intialize the store correctly.
Try this:
reducers/index.js
export default combineReducers({
// router reducer will be added automatically by connectRouter in store.js
search,
profile,
color,
categories,
coordinates: LocationReducer,
idprovider,
firstFavorite,
analytics,
sidebar,
messages,
total_messages,
onesignal,
tokens
});
store.js
import {connectRouter, routerMiddleware} from 'connected-react-router';
import {createBrowserHistory} from 'history';
import reducers from './reducers';
const history = createBrowserHistory(history);
const store = createStore(
connectRouter(history)(reducers),
applyMiddleware(routerMiddleware(history))
);

What is the use of autoRehydrate in redux-persist and why it was removed on v5?

I couldn't find anything on the GitHub page of ReduxPersist
I have a piece of code I'm trying to understand and as this autoRehydrate was removed, I would like to know how the code should be implemented with version 5 of redux-persist.
import { AsyncStorage } from 'react-native';
import { applyMiddleware, createStore } from 'redux';
import { autoRehydrate, persistStore } from 'redux-persist'
import thunk from 'redux-thunk';
import reducers from '../reducers';
const middleWare = [thunk];
const createStoreWithMiddleware = applyMiddleware(...middleWare)(createStore);
export default configureStore = (onComplete) => {
const store = autoRehydrate()(createStoreWithMiddleware)(reducers);
persistStore(store, { storage: AsyncStorage }, onComplete);
return store;
};
I've found some tutorials, but it just says this autoRehydrate must be there but doesn't explain what it actually does.
autoRehydrate means calling for the persist/REHYDRATE action to read the persisted state from the disk (which you have persisted before) which can be merged back to the original state.
In the migration guide from v4 to v5, they have introduced a PersistGate.
This delays the rendering of your app's UI until your persisted state has been retrieved and saved to redux.
Therefore all the rehydration actions will be handled by it under the hood.

Promise Redux : TypeError: next is not a function

I have a little app running on React + Redux with redux-promise middleware in order to deal with promise API call. I would like to manage the state of each api call (loading, success & error). So, as the official documentation says I change the applyMiddleware argument.
import React from 'react';
import ReactDOM from 'react-dom';
import promiseMiddleware from 'redux-promise';
import { Provider } from 'react-redux';
import { createStore, applyMiddleware } from 'redux';
import { Router, browserHistory } from 'react-router';
import reducers from './reducers';
import routes from './routes';
const createStoreWithMiddleware = applyMiddleware(
promiseMiddleware({
promiseTypeSuffixes: ['LOADING', 'SUCCESS', 'ERROR'],
}),
)(createStore);
ReactDOM.render(
<Provider store={createStoreWithMiddleware(reducers)}>
<Router history={browserHistory} routes={routes} />
</Provider>
, document.querySelector('.container'));
But when I change the appyMiddleware my app doesn't work anymore, I have this error showing on console:
TypeError: next is not a function
If I change back this line, everything works again as intended.
const createStoreWithMiddleware = applyMiddleware(promiseMiddleware)(createStore); // App works again
What's wrong?
Thank you,
I strongly believe that the way you create the store is incorrect.
In creating a store, there are 3 arguments,
createStore(reducer, preloadedState, enhancer) {...}
(1) reducer -> (required)
(2) preLoadedState -> (optional)
(3) enhancer -> (optional) // This is where your applyMiddleware should be passed. Hence, the minimal creation of a store is,
const store = createStore(() => {});
To answer your question, creating a store with a middleware should be,
const store = createStore(yourReducer, {}, applyMiddleware(promiseMiddleware))
or simply
const store = createStore(yourReducer, applyMiddleware(promiseMiddleware))
// This should also work because if the 2nd parameter is a function then it will be treated as the enhancer.

"No store found" when using Redux chrome extension

I have a problem with redux chrome extension.
I have the following code in my configureStore.js file :
import {createStore, applyMiddleware} from 'redux';
import rootReducer from '../reducers/index';
import thunk from 'redux-thunk';
export default function configureStore(initialState){
return createStore(
rootReducer,
initialState,
applyMiddleware(thunk),
window.devToolsExtension ? window.devToolsExtension() : f => f
);
}
I've added window.devToolsExtension ? window.devToolsExtension() : f => f like on the tutorial.
But when I try to run the extension I get
EDIT
import 'babel-polyfill';
import React from 'react';
import {render} from 'react-dom';
import {Router, browserHistory} from 'react-router';
import routes from './routes';
import '../node_modules/bootstrap/dist/css/bootstrap.min.css';
import './assets/sass/main.scss';
import '../node_modules/font-awesome/css/font-awesome.css';
import {loadCourses} from './actions/courseActions';
import {loadAuthors} from './actions/authorActions';
import {Provider} from 'react-redux';
import configureStore from './store/configureStore';
const store = configureStore();
store.dispatch(loadCourses());
store.dispatch(loadAuthors());
render(
<Provider store={store}><Router history={browserHistory} routes={routes}/></Provider>, document.getElementById("app")
);
Any advice?
I've got the solution from here.
The right code is :
import {createStore, applyMiddleware, compose} from 'redux';
import rootReducer from '../reducers/index';
import thunk from 'redux-thunk';
export default function configureStore(initialState){
return createStore(
rootReducer,
initialState,
compose(
applyMiddleware(thunk),
window.devToolsExtension ? window.devToolsExtension() : f => f
)
);
}
Ok, just checking the official repository of the Redux Dev Tools I found they recommend to use __REDUX_DEVTOOLS_EXTENSION__ instead of devToolsExtension as you are using.
So after just this update my code and de connectino with the plugin start working like a charm.
Here a sample code if it helps anyone:
const enhancers = compose(
window.__REDUX_DEVTOOLS_EXTENSION__ && window.__REDUX_DEVTOOLS_EXTENSION__()
);
const store = createStore(
rootReducer,
defaultState,
enhancers
);
There is a simpler solution now from the redux-devtools folks. See:
section 1.3 Use redux-devtools-extension package from npm at https://github.com/zalmoxisus/redux-devtools-extension
basically, if you npm install there redux-devtools-extension you can:
import { createStore, applyMiddleware } from 'redux';
import { composeWithDevTools } from 'redux-devtools-extension';
const store = createStore(reducer, composeWithDevTools(
applyMiddleware(...middleware),
// other store enhancers if any
));
In my case I only have one piece of middleware (redux-thunk) but I have an initialState so it looks like this:
const store = createStore(reducer, initalState, composeWithDevTools(applyMiddleware(thunk)))
store.subscribe(() => console.log("current store: ", JSON.stringify(store.getState(), null, 4)))
For anyone that none of these worked for, try restarting your server. I had tried for a while and then decided to restart my server. That solved it for me
As it is given in the original repository https://github.com/zalmoxisus/redux-devtools-extension, you must import compose as a named import and run this compose method by adding the applyMiddleware method as an input;
import { createStore, applyMiddleware, compose } from 'redux';
...
...
+ const composeEnhancers = window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ || compose;
+ const store = createStore(reducer, /* preloadedState, */ wcomposeEnhancers(
applyMiddleware(...middleware)
));
If anyone followed the same (or similar) boilerplate server-side rendering React app setup that I did, you may want to be sure if there are separate server and client files that use createStore(). In my case there were, and I spent a lot of time playing with the server file, when it needed to go into the client file.
Probably not the best way to do it, but alas, the boilerplate code I used did it that way.
I write a simple solution in the hope that it will be useful (It is not a definitive solution):
I have to right click on Redux Devtools Extension
Open Remote DevTools
Then change the Settings to use the custom server which is localhost:3000
And it works
I am late but may help someone, my solution was to use connect the component
import {connect} from 'react-redux'
...
class MyComponent extends Cmponent{
...
}
export default connect()(MyComponent)

Categories