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?
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.
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);
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..)
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);
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With