In React Native, I am using AsyncStorage to store the token on successful login, and remove it on successful logout using MobX actions in my AuthenticationStore.
I am trying to use a computed value, isAuthenticated which should be derived from the observable token. The token will either be null, if it does not exist in AsyncStorage, or be the AsyncStorage's token item value.
Here is some code to demonstrate:
class AuthenticationStore {
constructor() {
tokenStoredValue = AsyncStorage.getItem('token').then((data) => {
if(!data) { return null; }
else {return data; }
});
}
@observer token = this.tokenStoredValue;
@computed get isAuthenticated(){
return this.token ? true : false;
}
@action login(){
// more code above, here is the relevant setting of token
this.token = token;
AsyncStorage.setItem('token', token);
}
@action logout() {
this.token = null;
AsyncStorage.removeItem('token');
}
}
In my RN component, I have these 2 alerts to test this:
{AuthenticationStore.isAuthenticated && alert('Logged In')}
{!AuthenticationStore.isAuthenticated && alert('Logged Out')}
The issue is they alert after each other, I think because of the constructor/observer/computed combo of handling this situation. I think I have it setup incorrectly. Also, when I refresh the application Cmd+R in the simulator, after a logout, it alerts that I am logged in, so doesn't care about the tokenStoredValue...
What I am after is to check AsyncStorage for token, if it exists, then the @observable token should equal the stored token, and the isAuthenticated should be true. Otherwise, @observable token should be null and isAuthenticated should be false, and ofcourse only the one respective alert should alert based on isAuthenticated.
How can I get it to work?
I would do it like this:
class AuthenticationStore {
constructor() {
isAuthenticating = true
AsyncStorage.getItem('token').then(action((data) => {
this.token = data
this.isAuthenticating = false
}))
}
@observable isAuthenticating = false
@observable token = null
@computed get isAuthenticated () {
return this.token ? true : false
}
@action login () {
invariant(!this.isAuthenticating, 'Cannot login while authenticating.')
invariant(!this.isAuthenticated, 'Cannot login while authenticated.')
this.isAuthenticating = true
// more code above, here is the relevant setting of token
this.token = token
this.isAuthenticating = false
AsyncStorage.setItem('token', token)
}
@action logout () {
invariant(!this.isAuthenticating, 'Cannot logout while authenticating.')
invariant(this.isAuthenticated, 'Cannot logout while not authenticated.')
this.token = null
AsyncStorage.removeItem('token')
}
}
@ronag Thank you, refactoring the code worked.
@ronag what is the "action" . i am getting error .action is not defined
@11et401012 https://mobx.js.org/refguide/action.html
Most helpful comment
I would do it like this: