Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to keep user logged in (Aka, state persistency) in react-native

I am trying to keep a user logged in in my application. I tried several techniques but i have no idea on how i can read data back into the state when the application launches.

Right now i have the following:

const getInitialState = () => {
    var _initState = {
        auth: new AuthInitialState(),
        global: (new GlobalInitialState())
    };

    return _initState;
};

export default function configureStore() {


    const store = createStoreWithMiddleware(reducer, load(APP_STORAGE) || getInitialState());

    store.subscribe(() => {
        if(!load('debug')) {
            save(APP_STORAGE, store.getState());
        }
    });

    return store;
};

const createStoreWithMiddleware = applyMiddleware(
    thunk,
    localStorageMiddleware,
    logger
)(createStore)

In which the load and save methods are responsible for saving data to an AsyncStorage (using react-native-simple-store)

export const load = (key) => {
    return store.get(key);
}

export const save = async (key, data) => {
    store.save(key, JSON.stringify(data));
}

The render of my root is the current:

render() {
    const store = configureStore();

    return (
        <Provider store={store}>
            <MyApp/>
        </Provider>
    );
}

The data is being correctly saved (through the save subscriber) but it is not correctly reloaded on a hot reload or app relaunch. Thus my user ends up being logged out every time.

In the end i would also like to apply this technique to navigate to the correct page upon app startup.

Any recommendations on how i can approach this?

like image 262
Maxim Avatar asked Sep 19 '16 19:09

Maxim


People also ask

How do I stop a browser from going back to login form page once user is logged in?

You can use useEffect hook to handle this problem. IsAuth is a variable which returns true or false depending upon the token stored in localStorage. The empty array shows that useEffect will run only once the component is loaded. It means that once the user get logged in and tries to go to '/login' route.

How do I maintain a user session in react?

Focusing on redux-react-session , the first thing you need to do is add your session reducer. import { combineReducers } from 'redux'; import { sessionReducer } from 'redux-react-session'; const reducers = { // ... your other reducers here ... session: sessionReducer }; const reducer = combineReducers(reducers);


2 Answers

You can use redux-persist to achieve this:

import { createStore, applyMiddleware, compose } from 'redux';
import { persistStore, autoRehydrate } from 'redux-persist';
import { AsyncStorage } from 'react-native';

export default function configureStore() {

   const store = createStore(reducers, getInitialState(), compose(
       applyMiddleware([
           thunk,
           localStorageMiddleware,
           logger
       ]),
       autoRehydrate()
      )
   );

   persistStore(store, { storage: AsyncStorage });

   return store;
};

With this, each time your application load, the store is hydrated from the local storage. You don't have to deal with the AsyncStorage, everything is done automatically for you. You can read the docs of redux-persist to customize it per your needs (add a whitelist, a blacklist, a callback when the store is rehydrated..)

like image 76
Kerumen Avatar answered Nov 05 '22 00:11

Kerumen


Your basic approach looks good to me.

However, react-native-simple-store stringifies the state for you. As you run JSON.stringify() in your save function as well, it will not properly get decoded when it is loaded during the next start of your app.

See react-native-simple-store's codebase for more details.


To resolve this, remove JSON.stringify() from your save function:

export const save = async (key, data) => {
    store.save(key, data);
}
like image 26
TimoStaudinger Avatar answered Nov 04 '22 22:11

TimoStaudinger