Redux – How to use redux-persist for nested state in React Native?

Create your reducer

loginReducer.tsx

export const LOGIN = 'login/LOGIN';
export const SET_LOGGEDIN_USER = 'login/SET_LOGGED_IN_USER';

const initialState = {
  isLoggedIn: false,
  user: null,
};

const loginReducer = (state = initialState, action: any) => {
  switch (action.type) {
    case LOGIN: {
      return {
        ...state,
        isLoggedIn: action.data,
      };
    }
    case SET_LOGGEDIN_USER: {
      return {
        ...state,
        user: action.data,
      };
    }
    default: {
      return state;
    }
  }
};

export default loginReducer;

loginActions.tsx

import { LOGIN, SET_LOGGEDIN_USER } from './loginReducer';

export const login = (isLoggedIn: boolean) => ({
  type: LOGIN,
  data: isLoggedIn,
});

export const setLoggedInUser = (loggedInUser: object) => ({
  type: SET_LOGGEDIN_USER,
  data: loggedInUser,
});

Create persist reducer

reducers.tsx

import { combineReducers } from 'redux';
import { persistReducer } from 'redux-persist';
import AsyncStorage from '@react-native-community/async-storage';
import loginReducer from 'src/screens/login/state/loginReducer';
import homeReducer from 'src/screens/home/state/homeReducer';

const rootPersistConfig = {
  key: 'root',
  storage: AsyncStorage,
  blacklist: ['stateLogin', 'stateHome'],
};

const loginPersistConfig = {
  key: 'login',
  storage: AsyncStorage,
  whitelist: ['isLoggedIn'], // only persist "isLoggedIn"
};

const homePersistConfig = {
  key: 'home',
  storage: AsyncStorage,
  whitelist: ['token', 'userData'], // only persist "token", "userData"
};

const rootReducer = combineReducers({
  stateLogin: persistReducer(loginPersistConfig, loginReducer),
  stateHome: persistReducer(homePersistConfig, homeReducer),
});

export default persistReducer(rootPersistConfig, rootReducer);

Initiate store

store.tsx

import { compose, createStore, applyMiddleware } from 'redux';
import { createLogger } from 'redux-logger';
import { persistStore } from 'redux-persist';
import Reactotron from 'src/config/reactotron';
import rootReducer from './reducers';

const store = createStore(
  rootReducer,
  compose(applyMiddleware(createLogger()), Reactotron.createEnhancer())
);

const persistor = persistStore(store);

export { store, persistor };

Usage

import { PersistGate } from 'redux-persist/integration/react';
import { Provider } from 'react-redux';
import { store, persistor } from 'src/redux/store';
...

const App = () => {
   return (
       <Provider store={store}>
         <PersistGate loading={null} persistor={persistor}>
           <Routing />
         </PersistGate>
       </Provider>
   );
};
import React, { useEffect } from 'react';
import { NavigationContainer } from '@react-navigation/native';
import { LoginStack, MainStack } from 'src/routing/stacks';
import { getCurrentAuthUser } from 'src/api';
import { connect } from 'react-redux';
import { login } from 'src/screens/login/state/loginActions';

interface Props {
  reduxIsLoggedIn: boolean;
  reduxLogin: Function;
}

const Routing = (props: Props) => {
  const { reduxIsLoggedIn, reduxLogin } = props;

  useEffect(() => {
    const checkAuth = async () => {
      try {
        const user = await getCurrentAuthUser();
        if (!user) {
          reduxLogin(false);
        }
      } catch (error) {}
    };
    checkAuth();
    return () => {};
  }, [reduxLogin]);

  return (
    <NavigationContainer>
      {reduxIsLoggedIn ? <MainStack /> : <LoginStack />}
    </NavigationContainer>
  );
};

/////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////

const mapState = (state: any) => {
  return {
    reduxIsLoggedIn: state.stateLogin.isLoggedIn,
  };
};

const mapDispatch = (dispatch: Function) => {
  return {
    reduxLogin: (isLoggedIn: boolean) => dispatch(login(isLoggedIn)),
  };
};

export default connect(mapState, mapDispatch)(Routing);

1 Comment

Leave a Reply

Your email address will not be published.


*