redux-persist: undefined is not an object (evaluating store.getState) - react-native

It's my first time using Redux and Redux Persist.
I got this error when I tried to run my application (in index.js line 20):
TypeError: undefined is not an object (evaluating 'store.getState')
index.js:
import React from 'react';
import { AppRegistry } from 'react-native';
import App from './App';
import { name as appName } from './app.json';
import { Provider } from 'react-redux';
import {persistor, store}from './store/configureStore';
import { PersistGate } from 'redux-persist/integration/react';
const RNRedux = () => (
<Provider store={store}>
<PersistGate loading={null} persistor={persistor}>
<App/>
</PersistGate>
</Provider>
)
AppRegistry.registerComponent(appName, () => RNRedux);
App.js:
import {createStackNavigator, createAppContainer} from 'react-navigation';
import Register from './components/Register';
import Home from './components/Home';
import Login from './components/Login';
const AppNavigator = createStackNavigator({
HomeScreen: {
screen: Home,
navigationOptions: {
title: 'Home',
header: null
}
},
LoginScreen: {screen: Login},
RegisterScreen: {
screen: Register,
navigationOptions: {
title: 'Register'
}
}
});
const App = createAppContainer(AppNavigator);
export default App;
configureStore.js:
import { createStore, combineReducers } from 'redux';
import userReducer from './reducers/user';
import { persistStore, persistCombineReducers, persistReducer } from 'redux-persist';
import storage from 'redux-persist/es/storage' // default: localStorage if web, AsyncStorage if react-native
import { AsyncStorage } from 'react-native';
const persistConfig = {
key: 'root',
storage
};
const rootReducer = persistCombineReducers(persistConfig, {
user: userReducer
});
const persistedReducer = persistReducer(persistConfig, rootReducer);
export default () => {
let store = createStore(persistedReducer)
let persistor = persistStore(store, {storage: AsyncStorage})
return { store, persistor };
}

You are exporting a function from configureStore.js but trying to import {persistor, store} in index.js.
You should import the function instead and call it.
For example:
import configureStore from './store/configureStore';
const {store, persistor} = configureStore();

import thunk from "redux-thunk";
import { persistStore, persistReducer } from "redux-persist";
import { AsyncStorage } from "react-native";
import logger from "redux-logger";
const persistConfig = {
key: "root",
storage: AsyncStorage,
whitelist: ["authReducer"],
};
const persistedReducer = persistReducer(persistConfig, rootReducer);
const middleWares = [thunk, logger];
const store = createStore(persistedReducer, applyMiddleware(...middleWares));
let persistor = persistStore(store);
export default { store, persistor };
I was getting the same error "undefined is not an object (evaluating 'store.getState')"
My issue was solved after I removed the default keyword after export
export { store, persistor };

Related

How to persist redux data in react native

I’ve been struggling on this problem for while n now it’s a pretty simple issue I need a way to persist my data from redux into react native’s local storage I have tried using multiple approaches like the redux-persist library but I still have not been able to crack it… has anyone found a solution to this issue, I’m open to all approaches.
Here is the code I used for the redux-persist library
store.ts
import {createStore, combineReducers, applyMiddleware} from 'redux';
import thunk from 'redux-thunk';
import {persistStore} from 'redux-persist';
import authReducer from './reducers/authReducer';
import toastReducer from './reducers/toastReducer';
const rootReducer = combineReducers({
toast: toastReducer,
auth: authReducer,
});
export const Store = createStore(rootReducer, applyMiddleware(thunk));
export const PersistedStore = persistStore(Store);
export type RootState = ReturnType<typeof Store.getState>;
export type AppDispatch = typeof Store.dispatch;
authReducer.ts
import AsyncStorage from '#react-native-async-storage/async-storage';
import {persistReducer} from 'redux-persist';
import {AuthResponse} from '../../types/AuthResponse';
import {AuthReduxAction} from '../../types/ReduxActions';
import {SET_USER_DETAILS} from '../constants';
const persistConfig = {
key: 'root',
storage: AsyncStorage,
};
interface State {
userDetails: AuthResponse;
}
const initialState: State = {
userDetails: {},
};
const authReducer: (
state: State,
action: AuthReduxAction,
) => State | Promise<State> = async (state = initialState, action) => {
switch (action.type) {
case SET_USER_DETAILS:
// Saving user details to local storage
return {...state, userDetails: action.payload};
default:
return state;
}
};
export default persistReducer(persistConfig, authReducer);
App.tsx
import React from 'react';
import Routes from './Routes';
import {Provider} from 'react-redux';
import {PersistGate} from 'redux-persist/integration/react';
import {LogBox} from 'react-native';
import {PersistedStore, Store} from './redux/store';
LogBox.ignoreLogs(['new NativeEventEmitter']);
const App = () => {
return (
<Provider store={Store}>
<PersistGate loading={null} persistor={PersistedStore}>
<Routes />
</PersistGate>
</Provider>
);
};
export default App;
Here is the response I get when I print out the data (auth data in this case) from the redux store:
{"_U": 0, "_V": 0, "_W": null, "_X": null, "_persist": {"rehydrated": true, "version": -1}}
Any help would be appreciated
Thanks
I would like to do redux-persist this way and it works for several projects. Check it out if it works for you.
store.js
import { applyMiddleware, createStore, compose } from "redux";
import { persistStore, persistReducer } from "redux-persist";
import AsyncStorage from "#react-native-async-storage/async-storage";
import thunkMiddleware from "redux-thunk";
import { createLogger } from "redux-logger";
import reducer from "./reducers/";
const enhancers = [
applyMiddleware(
thunkMiddleware,
createLogger({
collapsed: true,
// eslint-disable-next-line no-undef
predicate: () => __DEV__,
})
),
];
/* eslint-disable no-undef */
const composeEnhancers =
(__DEV__ &&
typeof window !== "undefined" &&
window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__) ||
compose;
/* eslint-enable no-undef */
const enhancer = composeEnhancers(...enhancers);
const persistConfig = {
key: "root",
storage: AsyncStorage,
blacklist: [],
};
const persistedReducer = persistReducer(persistConfig, reducer);
export const store = createStore(persistedReducer, {}, enhancer);
export const persistor = persistStore(store);
authReducer.js
import {AuthResponse} from '../../types/AuthResponse';
import {AuthReduxAction} from '../../types/ReduxActions';
import {SET_USER_DETAILS} from '../constants';
interface State {
userDetails: AuthResponse;
}
const initialState: State = {
userDetails: {},
};
const authReducer: (
state: State,
action: AuthReduxAction,
) => State | Promise<State> = async (state = initialState, action) => {
switch (action.type) {
case SET_USER_DETAILS:
// Saving user details to local storage
return {...state, userDetails: action.payload};
default:
return state;
}
};
export default authReducer;
index.js (same location as authReducer.js)
import { combineReducers } from 'redux';
import authReducer from './authReducer';
import toastReducer from './toastReducer';
export default combineReducers({
authReducer ,
toastReducer
});

Redux-persist not persisting with expo on reload

I am using following tech stack
react-native
expo
redux
redux-persist.
I have tried articles, docs as well as questions here also but not help. Its simply not persisting. I am using emulator and running through expo only. As soon i close the app and reload expo client it simply doesn't persist and ask me to login again.
I also tried using AsyncStorage but still not working.
Hers's my code:
index.js
import thunk from "redux-thunk";
import AsyncStorage from "#react-native-community/async-storage";
import ExpoFileSystemStorage from "redux-persist-expo-filesystem"
// import storage from 'redux-persist/lib/storage';
import { createStore, applyMiddleware, compose } from "redux";
import { persistStore, persistReducer } from "redux-persist";
import rootReducer from "./reducers/rootReducer";
import logger from "redux-logger";
const persistConfig = {
key: "root",
storage: ExpoFileSystemStorage,
whitelist: ["authReducer"],
};
const composeEnhancers = window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ || compose;
const persistedReducer = persistReducer(persistConfig, rootReducer);
const store = createStore(
persistedReducer,
composeEnhancers(applyMiddleware(thunk, logger))
);
let persistor = persistStore(store);
export { store, persistor };
app.js
import React from "react";
import { Provider } from "react-redux";
import { PersistGate } from "redux-persist/integration/react";
import { AppLoading } from "expo";
import { useFonts } from "#use-expo/font";
import { NavigationContainer } from "#react-navigation/native";
import { ThemeProvider } from "react-native-elements";
import { theme } from "./constants/ThemeConfiguration";
import { store, persistor } from "./store";
import RootNavigator from "./navigators/RootNavigator";
export default (App) => {
let [fontsLoaded] = useFonts({
"Lato-Regular": require("./assets/fonts/Lato-Regular.ttf"),
});
if (!fontsLoaded) {
return <AppLoading />;
} else {
return (
<Provider store={store}>
<PersistGate loading={null} persistor={persistor}>
<ThemeProvider theme={theme}>
<NavigationContainer>
<RootNavigator />
</NavigationContainer>
</ThemeProvider>
</PersistGate>
</Provider>
);
}
};
rootReducer.js
import thunk from "redux-thunk";
import AsyncStorage from "#react-native-community/async-storage";
import { createStore, applyMiddleware, compose } from "redux";
import { persistStore, persistReducer } from "redux-persist";
import rootReducer from "./reducers/rootReducer";
import logger from "redux-logger";
const persistConfig = {
key: "auth",
storage: AsyncStorage,
};
const composeEnhancers = window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ || compose;
const persistedReducer = persistReducer(persistConfig, rootReducer);
const store = createStore(
persistedReducer,
composeEnhancers(applyMiddleware(thunk, logger))
);
let persistor = persistStore(store);
export { store, persistor };
I got it fixed. Its not there in any documentation or article. The problem is with the persistConfig. Key which is root here. It should be the name of the reducer which we want to persist. In my case it was auth.
Updated persistConfig will be as follows:
const persistConfig = {
key: "auth",
storage: AsyncStorage,
};

TypeError: cannot read property 'routes' of undefined

I'm using React-navigation 4 with redux and redux-helpers methods. We are trying to navigate through pages using NavigationAction, please find some of the details below:-
We have three steps process to login
validate contact no and then further process with password/OTP
To implement this functionality i have to dispatch and NavigationAction on the basis of some condition. But stucked in between routing.
here is my ConfigureStore.js
import { createStore, combineReducers, compose, applyMiddleware } from "redux";
import thunk from "redux-thunk";
import logger from 'redux-logger'
import uiReducer from "./reducers/ui";
// import navReducer from "./reducers/nav";
import authReducer from "./reducers/Auth";
import {
createReactNavigationReduxMiddleware,
createNavigationReducer,
} from 'react-navigation-redux-helpers';
import Navigator from '../router/router';
const navReducer = createNavigationReducer(Navigator);
const rootReducer = combineReducers({
ui: uiReducer,
nav: navReducer,
auth : authReducer
});
const navMiddleWare = createReactNavigationReduxMiddleware(
state => state.nav,
);
const configureStore = () => {
return createStore(rootReducer, applyMiddleware(thunk, logger, navMiddleWare));
};
export default configureStore;
Here is the Routes.js
import {
createAppContainer,
createSwitchNavigator
} from "react-navigation";
import { createStackNavigator } from 'react-navigation-stack';
import { createBottomTabNavigator } from 'react-navigation-tabs';
import LoginAuthScreen from './../screens/Auth/Login/Login';
import HomeScreen from './../screens/Home/Home';
import WorkoutScreen from './../screens/Workout/WorkoutScreen';
import HistoryScreen from './../screens/History/HistoryScreen';
import StudioScreen from './../screens/Studios/StudioScreen';
import footerComponent from './../component/Footer/Footer';
import AuthLoadingScreen from './../screens/Auth/AuthLoader';
import Step1 from './../screens/Auth/Login/Step1';
import Step2 from './../screens/Auth/Login/Step2';
AuthStack = createStackNavigator({
Login: {
screen: LoginAuthScreen,
navigationOptions: {
header: null,
}
},
LoginStep1: {
screen: Step1,
navigationOptions: {
header: null,
}
},
LoginStep2: {
screen: Step2,
navigationOptions: {
header: null,
}
}
})
TabNavigator = createBottomTabNavigator({
Home: HomeScreen,
Workout: WorkoutScreen,
Studio: StudioScreen,
History : HistoryScreen
}, {
tabBarComponent: footerComponent,
});
export default AppRouterConfig = createAppContainer(createSwitchNavigator(
{
AuthLoading: AuthLoadingScreen,
App: TabNavigator,
Auth: AuthStack,
},
{
initialRouteName: 'AuthLoading',
}
));
Index.js
import React, { Component } from 'react';
import { AppRegistry } from 'react-native';
import { name as appName } from './app.json';
import configureStore from './src/app/store/configureStore';
import { Provider, connect } from 'react-redux';
import { createReduxContainer } from 'react-navigation-redux-helpers';
import { Root } from 'native-base';
import Navigator from './src/app/router/router';
const store = configureStore();
const App = createReduxContainer(Navigator);
const mapStateToProps = (state) => ({
nav: state.nav,
});
const mergeProps = (state, dispatch, ownProps) => {
return ({
...ownProps,
screenProps: {
...ownProps.screenProps,
...state,
...dispatch,
}
})
}
const AppWithNavigationState = connect(mapStateToProps, null, mergeProps)(App);
class Main extends Component {
render() {
return (
<Provider store={store}>
<Root>
<AppWithNavigationState />
</Root>
</Provider>
);
}
}
AppRegistry.registerComponent(appName, () => Main);

how to use Redux with createSwitchNavigator?

I am trying to use switch navigator with redux. following is my code.
import { createSwitchNavigator, createStackNavigator } from 'react-navigation';
import LoginScreen from '../screens/LoginScreen';
import EmployeeListScreen from '../screens/EmployeeListScreen';
import DetailsView from '../screens/EmployeeDetailViewScreen';
import EmployeeForm from '../screens/EmployeeForm';
import AuthLoadingScreen from "../screens/AuthLoadingScreen.js";
import {connect } from "react-redux";
import { AppNavigator } from "../navigations/AppNavigator.js";
const AppStack = createStackNavigator({
List:{screen:EmployeeListScreen},
Detail:{screen:DetailsView},
Form:{screen:EmployeeForm}
});
const AuthStack = createStackNavigator({ Login: LoginScreen });
export const AuthNavigator = createSwitchNavigator(
{
AuthLoading: AuthLoadingScreen,
App: AppNavigator,
Auth: AuthStack,
},
{
initialRouteName: 'AuthLoading',
}
);
const AuthWithNavigationState = ({ dispatch, nav }) => (
<AuthNavigator />
);
const mapStateToProps = state => ({
nav: state.nav,
});
export default connect(mapStateToProps)(AuthWithNavigationState);
I'm importing this component is my App.js file and using it as follows to connect with redux store but it is giving me error like, React is not defined and error is located at connect(AuthWithNavigationState)
import React from 'react';
import { Provider } from 'react-redux';
import { createStore,applyMiddleware } from 'redux';
import thunk from 'redux-thunk';
import AppReducer from './src/reducers/AppReducer';
import AuthWithNavigationState from './src/navigations/AuthNavigator.js';
const store = createStore(AppReducer,applyMiddleware(thunk));
export default class App extends React.Component {
render() {
return (
<Provider store={store}>
<AuthWithNavigationState/>
</Provider>
);
}
}
I've tried to follow instruction from below link but still I am getting the same error.
how can i integrate redux store to react native?
Can anyone tell me what is wrong with my code?
after too much trying, I figure out that, The switch navigator don't need to be connect to the store, so below step was incorrect.
const AuthWithNavigationState = ({ dispatch, nav }) => (
<AuthNavigator />
);
const mapStateToProps = state => ({
nav: state.nav,
});
export default connect(mapStateToProps)(AuthWithNavigationState);
I simply exported AuthNavigator and imported in App.js and this worked for me.
import React from 'react';
import { Provider } from 'react-redux';
import { createStore,applyMiddleware } from 'redux';
import thunk from 'redux-thunk';
import AppReducer from './src/reducers/AppReducer';
import AuthNavigatorfrom './src/navigations/AuthNavigator.js';
const store = createStore(AppReducer,applyMiddleware(thunk));
export default class App extends React.Component {
render() {
return (
<Provider store={store}>
<AuthNavigator/>
</Provider>
);
}
}

No reducer for key (react native)

I am trying to integrate redux navigation to my existing app. It shows me the error No reducer provided for key navReducer. Any help is appreciated. Other stackoverflow answers point to the fact that there is problem in importing when this kind of error occurs but I am not sure why this is occuring in my case.
My /components/navigation.js:
import React, { Component } from 'react'
import { createStackNavigator } from 'react-navigation'
import Login from '../containers/loginContainer'
import Home from '../containers/homeContainer'
import {
reduxifyNavigator,
createReactNavigationReduxMiddleware,
createNavigationReducer,
} from 'react-navigation-redux-helpers'
export const RootStack = createStackNavigator(
{
Login: {
screen: Login,
},
Home: {
screen: Home,
},
},
{
initialRouteName: 'Login'
}
)
export const navReducer = createNavigationReducer(RootStack)
export const navigationMiddleware = createReactNavigationReduxMiddleware(
"root",
state => state.nav,
)
const appNavigator = reduxifyNavigator(RootStack, "root")
const mapStateToProps = (state) => ({
state: state.nav,
})
export const AppWithNavigationState = connect(mapStateToProps)(appNavigator)
My store configuration is:
import { createStore, applyMiddleware, compose } from 'redux'
import { persistStore, persistReducer } from 'redux-persist'
import thunk from 'redux-thunk'
import storage from 'redux-persist/lib/storage'
import rootReducer from './reducers'
import { navigationMiddleware } from './components/navigation'
const persistConfig = {
key: 'myKey',
storage,
}
const middlewares = [thunk, navigationMiddleware]
const persistedReducer = persistReducer(persistConfig, rootReducer)
const store = createStore(
persistedReducer,
{},
compose(
applyMiddleware(...middlewares)
)
)
const persistedStore = persistStore(store)
export default store
My root reducer looks something like this:
import { combineReducers } from 'redux';
import { navReducer } from '../components/navigation'
const rootReducer = combineReducers({
navReducer, // It throws the error here!!
})
export default rootReducer