Hi I am trying to setup redux-persist with react-redux, but I cant get it to work. I get the following error:
TypeError: _store2.default is not a function [Learn More] index.js:12:29
How I have the setup right now:
store.js
import {applyMiddleware, createStore} from 'redux';
import {persistStore,persistCombineReducers} from 'redux-persist';
import storage from 'redux-persist/es/storage' // default: localStorage if web, AsyncStorage if react-native
import { logger } from 'redux-logger';
import thunk from 'redux-thunk';
import promise from 'redux-promise-middleware';
import reducer from './reducers'
const middleware = applyMiddleware(promise(), thunk, logger);
const config = {
key: 'root',
storage,
};
const reducers = persistCombineReducers(config, {reducer});
export const configureStore = () => {
const store = createStore(reducers, middleware);
const persistor = persistStore(store);
return { persistor, store };
};
index.js
import React from 'react';
import ReactDOM from 'react-dom';
import {BrowserRouter} from 'react-router-dom';
import {Provider} from 'react-redux';
import Bootstrap from 'bootstrap/dist/css/bootstrap.css';
import './css/app.css';
import App from './containers/App';
import { PersistGate } from 'redux-persist/es/integration/react'
import configureStore from './store';
const { persistor, store } = configureStore()
ReactDOM.render(
<Provider store={store} >
<PersistGate persistor={persistor}>
<BrowserRouter>
<App/>
</BrowserRouter>
</PersistGate>
</Provider>,
document.getElementById('root')
);
UPDATE 1
Based on #azium's response now I get:
The above error occurred in the component:
in Connect(App) (created by Route)
in Route (created by withRouter(Connect(App)))
in withRouter(Connect(App))
in Router (created by BrowserRouter)
in BrowserRouter
in PersistGate
in Provider
When calling it like so from App.js:
#withRouter
#connect((store) => {
return {
isAuthenticated: store.auth.isAuthenticated,
};
})
If you want to use the default export you need to change:
export const configureStore = () => {
const store = createStore(reducers, middleware);
const persistor = persistStore(store);
return { persistor, store };
};
to:
export default () => {
const store = createStore(reducers, middleware);
const persistor = persistStore(store);
return { persistor, store };
};
or:
const configureStore = () => {
const store = createStore(reducers, middleware);
const persistor = persistStore(store);
return { persistor, store };
};
export default configureStore;
or if you don't want to use default export change:
import configureStore from './store';
to:
import { configureStore } from './store';
So after a bit of thinkering and community help I managed to narrow down the issue to my reducer declaration. I was declaring reducer in index.js with combineReducers whilst redux-persist says it shouldn't be.
Final index.js code:
import user from './userReducer'
import auth from './authReducer'
export default ({
user, auth
})
Related
I am getting the error :'TypeError: store.getState is not a function' and I can't determine where the problem is
here's how I created the store:
import { applyMiddleware, createStore } from 'redux';
import thunk from 'redux-thunk';
import rootReducer from './rootReducer';
const initialState = {
pending: false,
products: [],
error: null
}
const middlewares = [thunk];
export const store=createStore(rootReducer, initialState, applyMiddleware(...middlewares));
and here's the index.js:
import React from "react";
import ReactDOM from "react-dom";
import { Provider } from "react-redux";
import store from './App'
import App from "./App";
ReactDOM.render(
<Provider store={store}>
<App />
</Provider>,
document.getElementById("root")
);
and here's the thunk function:
function fetchProducts() {
return dispatch => {
dispatch(fetchProductsPending());
fetch('https://api.spacexdata.com/v3/launches')
.then(res => res.json()
)
.then(
res => {
if(res.error) {
throw(res.error);
}
dispatch(fetchProductsSuccess(res.products));
return res.products;
})
.catch(error => {
dispatch(fetchProductsError(error));
})
}
}
export default fetchProducts;
and here's a sandbox of the problem:
https://codesandbox.io/s/polished-sunset-wxefc?file=/src/index.js
here's a screenshot of the error:
The store is not the default export from the ./App.jsx module. You either need to add curly braces to your import or export store as the default:
// App.jsx
export const store = /* ... */
// index.js
import { store } from './App';
or
// App.jsx
export default const store = /* ... */
// index.js
import store from './App';
As the title says, I'm mapping through an array I have from an api in UserCardList component and it works fine but once I wrap App with PersistGate, it gives me "TypeError: users.map is not a function" and the error message from redux logger is "redux-persist: persist timed out for persist key "root". I really don't know what I'm doing wrong.
Any help would be highly appreciated.
index.js
import React from "react";
import ReactDOM from "react-dom";
import { BrowserRouter } from "react-router-dom";
import { Provider } from "react-redux";
import { PersistGate } from "redux-persist/integration/react";
import { store, persistor } from "./redux/store";
import "./index.css";
import "tachyons";
import App from "./containers/App";
ReactDOM.render(
<Provider store={store}>
<BrowserRouter>
<PersistGate persistor={persistor}>
<App />
</PersistGate>
</BrowserRouter>
</Provider>,
document.getElementById("root")
redux store
import { createStore, applyMiddleware } from "redux";
import { persistStore } from "redux-persist";
import thunkMiddleware from "redux-thunk";
import { createLogger } from "redux-logger";
import rootReducer from "../redux/root-reducer";
const logger = createLogger();
const middlewares = [logger, thunkMiddleware];
export const store = createStore(rootReducer, applyMiddleware(...middlewares));
export const persistor = persistStore(store);
export default { store, persistor };
root-reducer
import { combineReducers } from "redux";
import { persistReducer } from "redux-persist";
import storage from "redux-persist/lib/storage";
import requestUsers from "./reducers";
const persistConfig = {
key: "root",
storage,
whitelist: ["users"],
};
const rootReducer = combineReducers({
users: requestUsers,
});
export default persistReducer(persistConfig, rootReducer);
UserCardList component
import React, { Fragment } from "react";
import UserCard from "./UserCard";
const UserCardList = ({ users }) => {
return (
<Fragment>
<h1 className="f1"> Users </h1>
{users.map((user) => {
return (
<UserCard
key={user.login.uuid}
image={user.picture.large}
firstName={user.name.first}
lastName={user.name.last}
email={user.email}
city={user.location.city}
country={user.location.country}
/>
);
})}
</Fragment>
);
};
export default UserCardList;
I have created a sample project here by taking the code from your question and everything looks fine for me. And the store is getting created and users is coming as expected.
There could be a possible error in the reducers which is not posted here. Please have a look at the sample project, hope it helps.
I see in redux store you have this:
export const store = createStore(rootReducer, applyMiddleware(...middlewares));
export const persistor = persistStore(store);
// you dont need line below, you exported store and persistore in lines above
export default { store, persistor };
In my case, adding timeout: null to the persist configuration solved my issue.
const persistConfig = {
key: 'keyOfStore',
storage: storage,
// There is an issue in the source code of redux-persist (default setTimeout does not cleaning)
timeout: null,
}
const appReducer = combineReducers({
...otherReducers,
keyOfStore: persistReducer(persistConfig, keyOfStoreRedfucer),
})
Got the solution from here
I'm using redux-persist and I'm trying to render a screen passing it to the loading prop of PersistGate.
I did some research and I found that I should dispatch REHYDRATE to the reducer but that doesn't work either.
Maybe I'm not configuring my reducers well?
I would also like to be able to set the loading prop to null to avoid the flash screen before the App renders, but the result is the same as passing it a component to render.
This is my code of index.js
import App from './App';
import React from 'react';
import { Provider } from 'react-redux';
import { AppRegistry } from 'react-native';
import { PersistGate } from 'redux-persist/integration/react';
import { SplashScreen } from './src/screens/SplashScreen';
import configureStore from './src/store/configureStore';
const store = configureStore();
const persistor = configureStore();
const RNRedux = () => (
<Provider store={store}>
<PersistGate loading={<SplashScreen/>} persistor={persistor}>
<App />
</PersistGate>
</Provider>
);
componentDidMount = () => {
this.persistor.dispatch({ type: REHYDRATE });
};
AppRegistry.registerComponent('Sharryapp', () => RNRedux);
And that's my configureStore file:
import { createStore, combineReducers, applyMiddleware} from 'redux';
import ServerReducer from './reducers/ServerReducer';
import InviteReducer from './reducers/InviteReducer';
import { persistStore, persistReducer } from 'redux-persist';
import thunk from 'redux-thunk';
import storage from 'redux-persist/lib/storage';
const rootReducer = combineReducers({
server: ServerReducer,
invite: InviteReducer,
});
const persistConfig = {
key: 'root',
debug: true,
storage,
}
const persistedReducer = persistReducer(persistConfig, rootReducer);
const store = createStore(persistedReducer,applyMiddleware(thunk));
const persistor = persistStore(store);
export default configureStore = () => {
return ( store, persistor );
};
I am not sure why you wrap your store and persistor in a configureStore function.
Instead import both separately:
export const store = createStore(persistedReducer,applyMiddleware(thunk));
export const persistor = persistStore(store);
And import them in your desired file:
import {store, persistor} from './src/store/configureStore';
I have also noticed that your createStore call is false, since enhancers are passed as the third parameter. Change it to:
const store = createStore(persistedReducer, undefined, applyMiddleware(thunk));
That should do it.
Also you do not need to dispatch a rehydrate action as it happens automatically on app start.
I'm working on an app in react native and must work with Redux-Persist. I have the store configuration set up, no errors occur but the rehydration never happens and the persistentGate is infinitely in the loading state.
Here is my store.js
import { createStore, combineReducers } from 'redux';
import { persistStore, persistReducer } from 'redux-persist';
import storage from 'redux-persist/lib/storage';
import entriesReducer from './reducers/entries';
import autoMergeLevel2 from 'redux-persist/lib/stateReconciler/autoMergeLevel2';
const rootReducer = combineReducers({
entries : entriesReducer
});
const persistConfig = {
key: 'root',
storage: storage,
stateReconciler: autoMergeLevel2 // see "Merge Process" section for details.
};
const pr = persistReducer(persistConfig, rootReducer);
const configureStore = () => {
const store = createStore(rootReducer);
const persistor = persistStore(store);
return { persistor, store };
};
export default configureStore;
And my index.js
import React from 'react';
import { AppRegistry } from 'react-native';
import {Provider} from 'react-redux';
import App from './App';
import configureStore from './src/store/configureStore';
import { PersistGate } from 'redux-persist/lib/integration/react';
const store = configureStore();
const RNRedux = () => (
<Provider store={store.store}>
<PersistGate loading={<App />} persistor={store.persistor}>
<App/>
</PersistGate>
</Provider>
);
AppRegistry.registerComponent('PTM', () => RNRedux);
Any help will be very much appreciated, I've been trying to set this up for days now with no success. Previously I would have to deal with errors but now I don't see any and it still refuses to work, I simply don't know where to look for the fault.
Edit:
App.js file
import React from 'react';
import { View, Text, Button, StatusBar } from 'react-native';
import { StackNavigator } from 'react-navigation';
import {connect} from 'react-redux';
import NavBar from './src/components/NavBar/NavBar';
import DayPicker from './src/components/DayPicker/DayPicker';
import TotalTime from './src/components/TotalTime/TotalTime';
import HomeScreen from './screens/HomeScreen';
import DetailsScreen from './screens/DetailsScreen';
import EntriesList from './src/components/EntriesList/EntriesList';
var x = null;
const RootStack = StackNavigator(
{
Home: {
screen: HomeScreen,
},
Details: {
screen: DetailsScreen,
},
},
{
initialRouteName: 'Home',
}
);
export default class App extends React.Component {
render() {
return <RootStack />;
}
}
And my HomeScreen is using this:
const mapStateToProps = state => {
return {
data : state.entries.data,
entriesPerDay : state.entries.entriesPerDay,
pickedDate : state.entries.pickedDate,
total: state.entries.total
};
};
const mapDispatchToProps = dispatch => {
return {
onPickDate: (day) => dispatch(pickDay(day)),
onDataSet: (data) => dispatch(setData(data))
};
};
export default connect(mapStateToProps, mapDispatchToProps)(HomeScreen);
I am getting the following error on my react-redux & redux-persist setup:
The above error occurred in the component: in Connect(App) (created by
Route) in Route (created by withRouter(Connect(App))) in
withRouter(Connect(App)) in Router (created by BrowserRouter) in
BrowserRouter in PersistGate in Provider
I have it setup like this:
store.js
import {applyMiddleware, createStore} from 'redux';
import {persistStore,persistCombineReducers} from 'redux-persist';
import storage from 'redux-persist/es/storage' // default: localStorage if web, AsyncStorage if react-native
import { logger } from 'redux-logger';
import thunk from 'redux-thunk';
import promise from 'redux-promise-middleware';
import reducer from './reducers'
const middleware = applyMiddleware(promise(), thunk, logger);
const config = {
key: 'root',
storage,
};
const reducers = persistCombineReducers(config, {reducer});
export const configureStore = () => {
const store = createStore(reducers, middleware);
const persistor = persistStore(store);
return { persistor, store };
};
index.js
import React from 'react';
import ReactDOM from 'react-dom';
import {BrowserRouter} from 'react-router-dom';
import {Provider} from 'react-redux';
import Bootstrap from 'bootstrap/dist/css/bootstrap.css';
import './css/app.css';
import App from './containers/App';
import { PersistGate } from 'redux-persist/es/integration/react'
import configureStore from './store';
const { persistor, store } = configureStore()
ReactDOM.render(
<Provider store={store} >
<PersistGate persistor={persistor}>
<BrowserRouter>
<App/>
</BrowserRouter>
</PersistGate>
</Provider>,
document.getElementById('root')
);
App.js
import React from 'react'
import { withRouter, Switch, Route } from 'react-router-dom'
import { connect } from 'react-redux'
...
#withRouter
#connect((store) => {
return {
isAuthenticated: store.auth.isAuthenticated,
};
})
export default class App extends React.Component {
render() {
...
}
}
UPDATE 1
Full console log
UPDATE 2
Is this the right way to declare the reducer? It works fine without redux-persist
authReducer.js
export default function reducer(state = {
isAuthenticated: false
}, action) {
...
}
UPDATE 3
REHYDRATE console log
UPDATE 4
index.js (in reducers folder)
import { combineReducers } from 'redux';
import user from './userReducer';
import auth from './authReducer';
export default combineReducers({
user,
auth
})
So the problem was that one should not use both combineReducers and persistCombineReducers in one go. Similar situation could be found here https://github.com/rt2zz/redux-persist/issues/516