TL;DR: Configuring the Redux Toolkit store in React Native for HMR properly refreshes app on changes, but reducer behaviour does not change!
As seen in the React Native Reloading Announcement, HMR is supported for Redux within React Native, but the steps listed do not appear to work anymore. I have configured everything as mentioned in the announcement; however, the reducer reloading does not actually seem to change anything. When I edit a reducer, the app updates (reloading notification) but the reducer behaviour does not change!
// store/rootReducer.js
import { combineReducers } from "#reduxjs/toolkit";
import eventsReducer from "./slices/events";
import peopleReducer from "./slices/people";
const rootReducer = combineReducers({
events: eventsReducer,
people: peopleReducer,
});
export default rootReducer;
// store/index.js
import { configureStore } from "#reduxjs/toolkit";
import rootReducer from "./rootReducer";
const store = configureStore({
reducer: rootReducer,
});
if (process.env.NODE_ENV === "development" && module.hot) {
module.hot.accept(() => {
const newRootReducer = require("./rootReducer").default;
store.replaceReducer(newRootReducer);
});
}
export default store;
// App.js
import React from "react";
import { Provider } from "react-redux";
import store from "./store";
const App = () => {
return (
<Provider store={store}>
// ...ThemeProvider, Navigation scenes, etc
</Provider>
);
};
export default registerRootComponent(App);
Any ideas why this may be happening? I've been searching for related questions but cannot find anything from the recent past (ie. this year). Any older issues do not work either. My understanding is that I do not have to handle App HMR, as this is handled automatically by React Native. The announcement above makes it appear that adding HMR to Redux in React Native is super easy; however, it is has proven to not be the case.
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!
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.
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!
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)