6

in a react native app, i'm using redux. currently the whole app have single store and i use redux-persist to cache store to localstorage.

my app is username and password protected, you must create account to use it.

now i want to provide ability so that my user can switch between his accounts -if he have more than one account- . this is causing lots of trouble because now i have to clear storage and reset state everytime user switch between accounts.

so i was considering may be i can use multiple stores, one for every users ?

for example my app state looks like

{
  chat:{},
  highscores:{},
  gameHistory:{},
}

now if a user have account lets say User1@gmail.com the state will be populated with his data. and his state will be saved to LocalStorage,

once he switch account to User2@gmail.com now i have to reset the app to its initialState, then somehow load the User2 state from localStorage

i dont want the state of the app to be lost everytime user switch between accounts.

so i was considering may be in this case it would be a good option to use a multiple Redux Stores, one for every user.

did anyone had an app that is designed to be used by multiple users before ? how can we do this in redux ?

Zalaboza
  • 8,899
  • 16
  • 77
  • 142

2 Answers2

3

Well Answer above work fine, but since i'm using ImmutableJs, having a deeply nested objects can really be hard to handle.

so i ended up namespacing the Storage Key with user_id.

so now when ever i switch user, i just flush the whole store with this specefic user data from localStorage, or AsyncStorage.

i wrapped rootReducer in a simple reducer to handle this.

function makeRootReducer(rootReducer){
 return function reducer(state, action){
   if(action.type==='SWITCH_USER'){
      //LOAD USER DATA..
      const data = JSON.parse(localStorage.getItem("store.user."+action.id)||"{}");
      return makeInitialData(data); //this just return initialData.
    }
    let newState = rootReducer(state, action);
    //simple save state to localStorage if state changed
    if(state !== newState)localStorage.setItem('store.user.'+state.user_id',JSON.stringify(newState);
    return newState;
  }

}
Zalaboza
  • 8,899
  • 16
  • 77
  • 142
1

I don't think having a store for each user is a good idea. See this SO answer: https://stackoverflow.com/a/33633850/3794660

Why don't you namespace the data you have in your reducer by user id? Something like this:

{
  currentUserId: "1",
  chat:{ "1": { // Chats for user id 1 }, "2": { // Chats for user id 2 }},
  highscores:{ // Same structure as above },
  gameHistory:{ // Same structure as above },
}

When you switch user account, you simply update the currentUserId in the state.

I'd recommend using selectors to encapsulate the logic to read the data from the store.

A simple selector to get all the chats for the current account could look like this:

const getCurrUserId = state => state.currentUserId

const getChats = state => {
   const userId = getCurrUserId(state);
   return state.chat[userId];
}

You then use your simple getChats selector in your mapStateToProps to pass the data to your components. In this way you encapsulate the logic to retrieve the data from the state and your components don't need to know these details, so you're free to change your strategy if you need to.

Community
  • 1
  • 1
fabio.sussetto
  • 6,964
  • 3
  • 25
  • 37
  • I'd take it a step further and just map the user ID to their state instead of leaving it flat. It's a minor change, but seems cleaner to me. There's probably no great technical reason other than switching users back to one that was already loaded wouldn't require flushing state. – Dave Newton Oct 15 '16 at 19:45
  • @DaveNewton do you mind to elaborate? Not sure I get what you mean. – fabio.sussetto Oct 15 '16 at 20:01
  • Keep the users' state under a key that's their ID. – Dave Newton Oct 15 '16 at 20:41
  • I see, yeah that can be a way too. With my solution, why would it be necessary to flush the state when switching the user back? – fabio.sussetto Oct 15 '16 at 20:58
  • Oh, I misread your state-sorry. But IMO cleaner to put everything under a single ID key. – Dave Newton Oct 15 '16 at 21:45
  • I definitely see why you like it that way, how would you handle the initial state definition though? – fabio.sussetto Oct 15 '16 at 22:05
  • this would add a great deal of complexity to the selectors specialy since i'm using immutableJs and updating nested (denormalized) state tree can be a mess.. – Zalaboza Jun 19 '17 at 09:48