User login not persisting after app restart. Undefined returned when checking

Hello, I am using the Javascript SDK (npm package 3.0.11) with React Native, and am trying to get a user login session to persist after an app restart. I am successfully logging the user in with stayLoggedIn set to true in order to save the user login info, but after restarting the app and checking if the user is still logged in using Backendless.LocalCache.get(“current-user”) as suggested in the documentation, I get undefined returned. Is that not the method I should be using to check if the user login has persisted?

This is the documentation I am using: https://backendless.com/documentation/users/js/users_login.htm

Hi!

It looks like bug in documentation.
You can use:
Backendless.LocalCache.get(“current-user-id”) or
Backendless.LocalCache.get(“current-user-token”).
Also you can use method
Backendless.UserService.getCurrentUser().

It has been fixed in the docs.

When I use the first two lines you recommended, I still get undefined returned, and the third one returns null.

Is there way I can verify that the user info is actually being saved before I try to retrieve it?

I also tried setting the user id after successfully logging in, to see if I could retrieve it afterwards (without restarting the app), using the following: Backendless.LocalCache.set(“current-user-id”, user.objectId);
Then I tried to retrieve it on the next line using var userID = Backendless.LocalCache.get(“current-user-id”); but that still returned undefined.
I’m not even sure if that is what the set function is for, but I figured it was worth a shot. Either way, it seems to show that I can’t retrieve the user id even if the app isn’t restarted.

Unless you use some very old version of backendless.js or you do not set the stayLoggedIn argument to true, I cannot see how these calls would return undefined.

Do you use async API to login? If you do that, but check the values for user-token and userid before the result arrives, the values are indeed going to be undefined.

I don’t believe I am using an old version. As I mentioned, I am using the npm package 3.0.11, which is the latest version. Here are the exact lines I’m using. I init Backendless in a separate api.js file, and then get it using

var _Backendless = api.getBackendless();  

Then I log in using

_Backendless.UserService.login(this.fields.email, this.fields.password, true, new _Backendless.Async(this.loginSuccess.bind(this), this.loginError.bind(this)));

That works fine, and returns the user to the loginSuccess function. Inside that callback function, which is called by Backendless right after a succesful login, I try the following, which returns undefined:

var _userID = _Backendless.LocalCache.get("current-user-id");

The same line elsewhere also returns undefined after I restart the app. It seems like I’m doing everything properly, but it still doesn’t seem to want to work.

Is there any way I can look inside the LocalCache to see if the user info is actually being saved there?

Please pardon my ignorance, I am not too familiar with “React Native”… Does the script run in a browser or in a node environment?

If in a browser, you should see the state of LocalCache in local storage:
http://support.backendless.com/public/attachments/959840ebb6740c9d6645f84209211f4a.jpg</img>

I do use the async API, but I check the values after the result arrives, in the callback that is called when a successful result is returned.

React Native is a framework for making native mobile apps, and it runs off a node server and in an iOS simulator. There is a debugger that runs in Chrome where I can step through code etc., and I see the resources tab there but it looks empty (see screenshot below).

http://support.backendless.com/public/attachments/2fbb473fe95220f567578f67c315ece2.png</img>

Hi!

We will investigate how to add compatibility for react native apps.

Hi Pedram,

because of it’s impossible to use browser’s Local Storage in React Native (and Backendless rely on fact that storage exists always), I can only suggest you to find some alternative to Local Storage to emulate it’s work like native browser’s Local Storage.
We need to store user’s object somewhere and LS is the best way to do it in most cases.
If you have an idea on how to store it for using SDK in React Native, you’re welcome to share it. :slight_smile:

Regards,
Stanislav

Hi Stanislav,
React Native has its own storage system called AsyncStorage (https://facebook.github.io/react-native/docs/asyncstorage.html). The docs say “AsyncStorage is a simple, asynchronous, persistent, key-value storage system that is global to the app. It should be used instead of LocalStorage.”. Perhaps that could be integrated into Backendless in cases where RN is being used?

I have also used react-native-simple-store in the past, and will try to use it in this circumstance to store the user object returned from a successful login. However, once I retrieve the object back from storage, I’m not sure how to pass it to the user service in order to verify that the token is still valid, since I assume that the isValidLogin() method will try to retrieve the user object from LocalStorage. Is there a way to do give IsValidLogin my own user object?

Hi Pedram,

Sorry for the long delay with answer.

You are quite right, there is the AsyncStorage in React-Native that can be used for same purposes as the localStorage in browsers.
Unfortunately, we can’t use it in our JS SDK because of other consumers of SDK besides React-Native.
But I can give you some workaround tips.
Firstly, please update backendless npm module up to v3.1.13.
For ‘IsValidLogin’ correct working, it needs that there are ‘user-token’ and ‘current-user-id’ in the LocalCache of Backendless.
That’s why after a user successfully logged in we need store this property in AsyncStorage.
For example:


logIn() {
    const login = this.state.email;
    const password = this.state.password;
    const stayLoggedIn = this.state.stayLoggedIn;


    Backendless.UserService.login(login, password, stayLoggedIn, new Backendless.Async(onUserLoggedIn, onError);


    function onUserLoggedIn() {
        if (stayLoggedIn) {
          	const userData = {
            	token: Backendless.LocalCache.get('user-token'),
            	id: Backendless.LocalCache.get('current-user-id')
        	};


        	AsyncStorage.setItem('user', JSON.stringify(userData), (err) => {});
       }
    }
}

And we need to restore those properties and set them back to Backendless.LocalCache right before checking if a user has already logged in.
For example:


isUserLoggedIn () {
    AsyncStorage.getItem('user', (err, user) => {
        if (user) {
            user = JSON.parse(user);


            Backendless.LocalCache.set('user-token', user.token);
            Backendless.LocalCache.set('current-user-id', user.id);
            Backendless.LocalCache.set('stayLoggedIn', true);


            Backendless.UserService.isValidLogin(new Backendless.Async(() => {
                console.log('User are staying logged in');
            }, onError));
        }
    });
}

Of course, you can use any module instead of AsyncStorage, I’ve chosen it just for examples.

I hope my tips will be helpful for you.
Please, let us know about your results.
Regards, Ilya

1 Like

Thanks for the reply Ilya. Because of this issue I moved on to another back end solution and reworked my code to use that, but I hope that others who are trying to use Backendless with React Native will find this helpful.

Hi, any news about react native support?

1 Like