I have a native Android app that now has a React-Native part to it.
In short, i have a list view in native Android/Java. When i tap a row, i start a new Activity which leads to the React-Native code.
The components make an API call, but before it does it, my code goes through the React Native module to get a value from the User Preferences in the Java/Android settings for the header so that it can make the proper API call.
The React Native API call in /actions/index.js
:
export const toggleBlocked = (user_id) => async dispatch => { try { let headers = await getHeaders(); const response = await fetch('http://my.domain.com/api/get_data?user_id=`${user_id}`', { headers, method: 'GET' }); if (response.status == 200) { // do stuff } else { ToastAndroid.show("Looks like the response wasnt good :(", ToastAndroid.LONG, ToastAndroid.CENTER); } } catch (error) { ToastAndroid.show("An Error Occurred :(", ToastAndroid.LONG, ToastAndroid.CENTER); } }; function getHeaders() { let userId = UserService.getUserId() console.log("2. React-Native | getHeaders... user_id is " + userId) return ( new Headers({ Cookie: `abcxyz=${userId}`, user_id: userId, "User-Agent": "android", "Content-Type": "application/json", charset: "utf-8", "app-version": "9.1.23", Accept: "application/json" }) ) }
Back in native Android/Java, i have my modules and packages set up. Here is UserServiceModule.java
:
@ReactMethod public int getUserId() { SharedPreferences settings = mContext.getSharedPreferences(Constants.SettingsPreference, Context.MODE_PRIVATE); int userId = settings.getUserId(); Log.d(TAG, "1. Java/Android code. UserID is " + userId); return userId; }
When i run the code, user_id is always null. I even expected my logs to show in order (see the numbered logs), but they’re reverse??
"1. Java/Android code. UserID is 123" "2. React-Native | getHeaders... user_id is 123"
Any insights would be great please. Thanks.
UPDATE / SOLUTION Here is the updated changes to get things working correctly:
@ReactMethod public void getUserId(final Promise promise) { SharedPreferences settings = mContext.getSharedPreferences(Constants.SettingsPreference, Context.MODE_PRIVATE); int userId = settings.getUserId(); Log.d(TAG, "1. Java/Android code. UserID is " + userId); promise.resolve(Integer.toString(userId)); }
Advertisement
Answer
@ReactMethod functions are always suppose to return void and are asynchronous. The reason you are getting null is because your JS code is written synchronously. It initializes the variable userId as null and sets it with the return value of the asynchronous call. But because the code you written was synchronous, it will go to the next line before the react method comes back with the value.
You will need to do an async await like you did with your dispatch method. However that won’t be enough as react methods return a void value. Quite frankly I don’t know how a method not found error was not triggered instead. Perhaps @ReactMethod ignores the return value you defined in Java?
Regardless, after setting up the async await. Do something similar to what they did here: https://facebook.github.io/react-native/docs/native-modules-android.html#callbacks