React Native project - cannot make API calls with AwsAmplify through custom library - react-native

I have a react-native app (without expo) called myapp.
I have a private custom package called myapp-core, where I handle AwsAmplify services (Auth, Storage) - to do login/signOut/etc.
I want to use myapp-core in myapp project, so I added it as a dependency in package.json ("myapp-core": "file:../myapp-core",) and then yarn install.
The problem I’m facing is that when I call myapp-core.authService.login(username, password) from the mobile project, I catch the error:
“ { “line”:177826, “column”: 17, “sourceURL”:
“http://10.0.2.2:8081/index.delta?platform=android&dev=true&minify=false”
} ”
From my research, that means my custom library cannot make api calls - but I don’t know exactly.
When I use aws-amplify's Auth object directly in my mobile project, it works.
Hopefully relevant code:
/**=============================**/
/** myapp/CoreServices.js **/
import { AmplifyService } from “myapp-core";
export default class CoreServices {
constructor() {
AmplifyService.configure();
const auth = AmplifyService.authService();
auth
.login(“myusername”, “mypassword”)
.then(user => console.warn("success", user))
.catch(error => console.warn("error", error));
}
}
/**=============================**/
/** myapp-core/AmplifySevice.js **/
import Amplify from 'aws-amplify';
import AuthService from '../AuthService/AuthService';
import awsConfigs from '../aws-exports';
class AmplifyService {
static authServiceInstance = null;
static storageServiceInstance = null;
static configure(config = awsConfigs) {
if (config === null || config === undefined) {
throw new Error('AmplifyService must be initialized with Auth and Storage configurations.');
}
Amplify.configure({
Auth: { /*...*/ },
Storage: { /*...*/ }
});
}
static authService() {
if (!this.authServiceInstance) {
this.authServiceInstance = new AuthService();
}
return this.authServiceInstance;
}
static storageService() {
console.warn('storage service');
// initialize storage service
// return storage service
}
}

I managed to solve my project's issue.
Maybe someone will benefit from my solution.
The problem didn't have anything to do with AwsAmplify, but with the way I linked the projects: myapp-core with myapp.
The issue was that in the myapp-core I am using the aws-amplify package that I would normally link to the mobile projects (react-native link) but in my case I assumed (wrongly) that it wouldn't be the case.
The solution was to link whatever packages were needed in the iOS/Android projects to install the proper pods/gradle libraries, like react-native link amazon-cognito-identity-js for authentication.
... and now I am finally happy :))
Links that shed some light:
https://github.com/facebook/create-react-app/issues/1492
https://eshlox.net/2018/11/12/aws-amplify-react-native-typeerror-cannot-read-property-computemodpow-of-undefined/
In case somebody thinks this isn't the solution and I got lucky or something, please comment or post another response.

Related

Why Vercel Web vitals is not loading for my Astro Project?

I created a landing page using Astro with Tailwind CSS. And it is currently hosted on Vercel. I wanted to try out the analytics service provided by Vercel. I have been able to avail the Audience analytics service provided by Vercel. However, I cannot avail the web vitals services. After enabling the service and redeploying my project, I am stuck in this screen (screen shot provided).
Please note that I did turn off the ad blocker but that did not resolve the issue.I also added the following meta tag to resolve any CSP issue
<meta http-equiv="Content-Security-Policy"
content="default-src 'self' vitals.vercel-insights.com"/>
But that has not solved the problem.That is why I want to know does Vercel support analytics for Astro projects and if they do, then what am I doing wrong? Thank you.
Vercel’s Web Vitals analytics currently only has out-of-the-box support for Next, Nuxt, and Gatsby.
To track Web Vitals with a different framework like Astro, you need a bit of manual set up work as documented in Vercel’s Web Vitals API docs.
For example in your base Astro layout you could include a script tag that will import their example code and run it:
---
// src/layouts/BaseLayout.astro
---
<script>
import { webVitals } from '../scripts/vitals';
const analyticsId = import.meta.env.PUBLIC_VERCEL_ANALYTICS_ID;
webVitals({
path: window.location.pathname,
analyticsId,
});
</script>
Here’s Vercel’s example vitals.js snippet:
// src/scripts/vitals.js
import { getCLS, getFCP, getFID, getLCP, getTTFB } from 'web-vitals';
const vitalsUrl = 'https://vitals.vercel-analytics.com/v1/vitals';
function getConnectionSpeed() {
return 'connection' in navigator &&
navigator['connection'] &&
'effectiveType' in navigator['connection']
? navigator['connection']['effectiveType']
: '';
}
function sendToAnalytics(metric, options) {
const body = {
dsn: options.analyticsId, // qPgJqYH9LQX5o31Ormk8iWhCxZO
id: metric.id, // v2-1653884975443-1839479248192
page: options.path, // /blog/my-test
href: location.href, // https://my-app.vercel.app/blog/my-test
event_name: metric.name, // TTFB
value: metric.value.toString(), // 60.20000000298023
speed: getConnectionSpeed(), // 4g
};
if (options.debug) {
console.log('[Analytics]', metric.name, JSON.stringify(body, null, 2));
}
const blob = new Blob([new URLSearchParams(body).toString()], {
// This content type is necessary for `sendBeacon`
type: 'application/x-www-form-urlencoded',
});
if (navigator.sendBeacon) {
navigator.sendBeacon(vitalsUrl, blob);
} else
fetch(vitalsUrl, {
body: blob,
method: 'POST',
credentials: 'omit',
keepalive: true,
});
}
export function webVitals(options) {
try {
getFID((metric) => sendToAnalytics(metric, options));
getTTFB((metric) => sendToAnalytics(metric, options));
getLCP((metric) => sendToAnalytics(metric, options));
getCLS((metric) => sendToAnalytics(metric, options));
getFCP((metric) => sendToAnalytics(metric, options));
} catch (err) {
console.error('[Analytics]', err);
}
}
For a slightly more real-world implementation you, check out the <TrackVitals> Astro component in the astro-badge repo.
Vercel analytics has support for frameworks other than Next, Nuxt Gatsby etc. The way to achieve it in Astro (1.6, 2.0 etc.) is to install the #vercel/analytics package and inject a simple <script> tag that imports it and calls its exported function inject():
<script>
import { inject } from '#vercel/analytics'
// #ts-ignore: process.env.NODE_ENV is required by #vercel/analytics internally
// so that it can determine the correct path for importing the analytics script
globalThis.process = { env: { NODE_ENV: import.meta.env.MODE } }
inject()
</script>
You can inject this code in your <head> section in any .astro template file.
Unfortunately, the package is expecting a non-ESM runtime environment and is internally conditionally checking for process.env.NODE_ENV to determine which script to load (local-relative path to JS or from a remote host, fully qualified domain name). This is the reason, the MODE needs to be exposed as process.env.NODE_ENV. I tried to achieve this via Vite using define, but Astro seems to check for process somewhere else internally and fails.

How to use "promptAsync" from expo-auth-session, old library used in video tutorial was deprecated

I have been following the tinder 2.0 react native tutorial https://youtu.be/qJaFIGjyRms At 1:04:00 he sets the sign in method to: "await Google.logInAsync()" but I have noticed the google app auth library used in the video is now deprecated, I am redirected to use expo auth session instead but I notice there is a slight difference, where they used "await Google.logInAsync()" I must put "promptAsync" instead, when I do this I get the error promptAsync is undefined, I try with google.loginasync and get the same error that it is still undefined, what should I do? screenshot
code:
import React, { createContext, useContext } from 'react'
//import * as Google from 'expo-auth-session/providers/google';
import * as Google from 'expo-google-app-auth';
const AuthContext = createContext({});
const config = {
androidClientId:
'236293699216-9a0nknjdq7ie79h40iubg0tddokgogfv.apps.googleusercontent.com',
iosClientId:
'236293699216-6jdpm0rd6kn5d0qlbh1vgva5afgbqgib.apps.googleusercontent.com',
scopes: ["profile", "email"],
permissions: ["public_profile","email", "gender", "location"],
}
export const AuthProvider = ({ children}) => {
const signInWithGoogle = async() => {
await Google.logInAsync(config).then(async (logInResult) => {
if (logInResult.type === "success") {
// login
}
});
};
return (
<AuthContext.Provider
value={{
user: null,
signInWithGoogle
}}
>
{children}
</AuthContext.Provider>
)
}
export default function useAuth() {
return useContext(AuthContext);
}
I sought help on the forum that belongs to the maker of the video and other people had come across the same issue, one person recommended to go into package.json find the installed dependencies and change “expo-google-app-auth” from “^10.0.0” to “~9.0.0” and then npm I in the terminal, I have done this and I'm now getting the error “no such file or directory /Users/shangefagan/twinder-3/node_modules/expo-google-app-auth/node-modules/react-native/package.json” I have changed it back to “^10.0.0” but still getting the same error, screenshot
do I just npm uninstall expo-google-app-auth and try to use expo-auth-session as I was originally trying? if so What is the correct way to use promptAsync from the expo-auth-session library
I check the docs for both libraries, expo google app auth: https://docs.expo.dev/versions/v43.0.0/sdk/google/ and expo auth session: https://docs.expo.dev/versions/latest/sdk/auth-session/ but I am unsure exactly how to use the new login method "promptAsync"
To use promptAsync you have to use the package expo-auth-session. Like you said expo-google-app-auth is deprecated.

TypeError Object is not a constructor (evaluating new_pubnubReact.default')

I am new to react native and am trying to create push notifications for android.
I am using the following tutorial from PubNub.
PubNub tutorial
When I run my app in the android studio emulator after finishing the tutorial I get the following error.
Not quite sure what it means of how to fix it as when I google the problem nothing comes up.
Here is my code
import React from 'react';
import PushNotificationIOS from 'react-native';
import PubNubReact from 'pubnub-react';
const PushNotification = require('react-native-push-notification');
export default class App extends React.Component {
constructor(props) {
super(props);
this.pubnub = new PubNubReact({
publishKey: 'YOUR_PUBNUB_PUBLISH_KEY_HERE',
subscribeKey: 'YOUR_PUBNUB_SUBSCRIBE_KEY_HERE'
});
this.pubnub.init(this);
PushNotification.configure({
// Called when Token is generated.
onRegister: function(token) {
console.log( 'TOKEN:', token );
if (token.os == "ios") {
this.pubnub.push.addChannels(
{
channels: ['notifications'],
device: token.token,
pushGateway: 'apns'
});
// Send iOS Notification from debug console: {"pn_apns":{"aps":{"alert":"Hello World."}}}
} else if (token.os == "android"){
this.pubnub.push.addChannels(
{
channels: ['notifications'],
device: token.token,
pushGateway: 'gcm' // apns, gcm, mpns
});
// Send Android Notification from debug console: {"pn_gcm":{"data":{"message":"Hello World."}}}
}
}.bind(this),
// Something not working?
// See: https://support.pubnub.com/support/solutions/articles/14000043605-how-can-i-troubleshoot-my-push-notification-issues-
// Called when a remote or local notification is opened or received.
onNotification: function(notification) {
console.log( 'NOTIFICATION:', notification );
// Do something with the notification.
// Required on iOS only (see fetchCompletionHandler docs: https://reactnative.dev/docs/pushnotificationios)
// notification.finish(PushNotificationIOS.FetchResult.NoData);
},
// ANDROID: GCM or FCM Sender ID
senderID: "sender-id",
});
}
}
pubnub-react library has been completely changed in version 2.0.0. It no longers includes pubnub JavaScript SDK by default so you have to install it as well.
Here is the link to new PubNub React repository, and in the README.md file you can find examples on how to use it.
If you want to use the older version that is compatible with the tutorial/blog post you may be reading, please install the older version of the PubNub React SDK like so:
$ npm install pubnub-react#1
To summarize the changes, pubnub-react now uses Context and Hooks API to propagate PubNub instance deep into the children tree.
Provider
You need to include the provider somewhere top in the component tree.
import React from 'react'
import PubNub from 'pubnub'
import { PubNubProvider } from 'pubnub-react'
const pubnub = new PubNub({}) // PubNub configuration
export const App = () => {
return <PubNubProvider client={pubnub}>
<Child />
</PubNubProvider>
}
Consumer
To use the PubNub instance somewhere else, you can now just use the usePubNub hook.
import { usePubNub } from 'pubnub-react'
export const Child = () => {
const pubnub = usePubNub()
return <div>I am using PubNub!</div>
}

How to get Expo static deep link for development?

I need an Expo static deep link for development to use for Oauth redirect with a 3rd party ( Cognito )
I have used Linking.makeUrl() but this returns a deep link with a dynamic local ipaddress
exp://10.0.0.107:19000 that will not be consistent for other developers on the team.
The documentation at:
https://docs.expo.io/versions/latest/workflow/linking/#linking-module
Says the various environment links look like
Published app in Expo client : exp://exp.host/#community/with-webbrowser-redirect
Published app in standalone : myapp://
Development : exp://wg-qka.community.app.exp.direct:80
I have tried that Development link but it fails to open.
I have the similar issue too, here is my solution
Also post in https://github.com/aws-amplify/amplify-js/issues/4244#issuecomment-586845322
In case anyone still needs help for expo+amplify+social logins
app.json
{
"expo": {
"scheme": "exposchemeappname://" // use any name you like, just make it unique
}
}
App.js
import { Linking } from 'expo';
import * as WebBrowser from 'expo-web-browser';
import awsconfig from './aws-exports';
const amplifyConfig = {
...awsconfig,
oauth: {
...awsconfig.oauth,
urlOpener: async (url, redirectUrl) => {
// On Expo, use WebBrowser.openAuthSessionAsync to open the Hosted UI pages.
const { type, url: newUrl } = await WebBrowser.openAuthSessionAsync(url, redirectUrl);
if (type === 'success') {
await WebBrowser.dismissBrowser();
if (Platform.OS === 'ios') {
return Linking.openURL(newUrl);
}
}
},
options: {
// Indicates if the data collection is enabled to support Cognito advanced security features. By default, this flag is set to true.
AdvancedSecurityDataCollectionFlag: true
},
}
};
const expoScheme = "exposchemeappname://"
// Technically you need to pass the correct redirectUrl to the web browser.
let redirectUrl = Linking.makeUrl();
if (redirectUrl.startsWith('exp://1')) {
// handle simulator(localhost) and device(Lan)
redirectUrl = redirectUrl + '/--/';
} else
if (redirectUrl === expoScheme) {
// dont do anything
} else {
// handle the expo client
redirectUrl = redirectUrl + '/'
}
amplifyConfig.oauth.redirectSignIn = redirectUrl;
amplifyConfig.oauth.redirectSignOut = redirectUrl;
Amplify.configure(amplifyConfig);
Make sure you add the following redirect urls to amplify amplify auth update
# development
exp://127.0.0.1:19000/--/
exp://192.168.1.101:19000/ # depends on your lan ip
# expo client
exp://exp.host/#[EXPO_ACCOUNT]/[EXPO_APPNAME]/
# expo scheme for standalone
exposchemeappname://
you can use Linking module
install it by running: expo install expo-linking
import it at the top of your file: import * as Linking from "expo-linking";
and then use: Linking.makeUrl(); to get the link to your app hosted by expo client
console it to see the url

Unable to include AB Testing for React Native application

I am integrating A/B Testing for my React Native application using Firebase. I have tried two methods - using react-native-ab and react-native-ab-test.
In the first case, I get an error saying "undefined is not an object(evaluating PropTypes.string)"
In the second case, I get an error saying "index.ios.js tries to require 'react-native' but there are several files providing this module. You can delete or fix them."
In both the cases, I get these errors just by importing the dependency in my JS file. By seeing the github pages of both dependencies, I think there is no need to link both the dependencies and they run fine.
Links :
https://github.com/lwansbrough/react-native-ab
https://github.com/landaio/react-native-ab-test
I installed it with this module and it works perfectly, you can try this:
https://github.com/invertase/react-native-firebase
https://rnfirebase.io/docs/v5.x.x/getting-started
and then it is to configure the remote config so that the a-b test works for you
https://rnfirebase.io/docs/v5.x.x/config/reference/config
I'm using A/B testing and works for me with this module:
"react-native-firebase": "3.3.1",
and needs pod too.
pod 'Firebase/Core', '~> 5.11.0'
pod 'Firebase/RemoteConfig', '~> 5.11.0'
My logic
import firebase from 'react-native-firebase';
setRemoteConfigDefaults() {
if (__DEV__) {
firebase.config().enableDeveloperMode();
}
// Set default values
firebase.config().setDefaults({
my_variant_remote_config_param: ''
});
}
/**
* FIREBASE remote config fetch
* #param valueToFetch: remote config key
*/
export const fetchRemoteConfig = async (valueToFetch: RemoteConfigKeysTypes): Promise<string> => {
try {
await firebase.config().fetch();
await firebase.config().activateFetched();
const snapshot = await firebase.config().getValue(valueToFetch);
const response = snapshot.val();
return response;
} catch (error) {
firebase.analytics().logEvent('remote_config_get_value_error', { error, key: valueToFetch });
return null;
}
};
More Info:
https://www.npmjs.com/package/react-native-firebase