Open host's browser from simulator? - react-native

On latest react-native 0.60 onwards, the default app will include a list of links at landing page as below
Now if this react-native project running on simulator and we click on one of the link, it will open up on our laptop instead of opening on browser from within the simulator. I'm wondering how it works so I took a look at node_modules/react-native/Libraries/Core/Devtools/openURLInBrowser.js and found below code
'use strict';
const getDevServer = require('./getDevServer');
function openURLInBrowser(url: string) {
// Made a console.log here and getDevServer().url = http://localhost:8081
fetch(getDevServer().url + 'open-url', {
method: 'POST',
body: JSON.stringify({url}),
});
}
module.exports = openURLInBrowser;
Despite having this source code, I still can't understand how can we use a fetch library to launch a url in host's browser? So far I've only use fetch to perform http request from some backend but apparently there's something more that fetch is providing?

The Metro bundler is running on 8081. fetch is performing a HTTP POST request to http://localhost:8081/open-url. Metro is able to handle this request and open up the browser accordingly.
An example Express web server may handle it like so:
app.post('/open-url', req => {
const { url } = req.body;
// Handle code to open URL
});

Related

react native supabase facebook login redirect callback site url

I am trying to login with facebook using Supabase on ios emulator. After logging in with Facebook, it redirects me back to localhost. I don't know exactly what to do on this side. Can you help me? I'm still very new.
const onHandleLogin = async () => {
const {data, error} = await supabase.auth.signInWithOAuth({
provider: 'facebook',
});
if (error) {
return;
}
if (data.url) {
const supported = await Linking.canOpenURL(data.url);
if (supported) {
await Linking.openURL(data.url);
}
}
};
After the login process, it still stays on the localhost address on the browser. My purpose is to send it to the application and get token information via the url, but I have no idea how.
I think I need to make changes here but I don't know what to write in the site url because it is a mobile application.
Thanks for your support and replies.
I tried to login with facebook using supabase, but after logging in, it keeps me in safari and gives token information on localhost. I want to direct the application after the login process and get the token information.
You will need to create a deep link for your React Native app: https://reactnative.dev/docs/linking and then set this as your redirect URL. Here a similar example with Flutter: https://supabase.com/docs/guides/getting-started/tutorials/with-flutter#setup-deep-links

How to make a fetch request to localhost in React Native/Expo?

I'm creating a React Native/Expo app that uses Deno on the backend. I've created an API in the backend that I can run locally on localhost:4000. When I try to use fetch to call the API in the Expo app, however, I keep getting an error
[Unhandled promise rejection: TypeError: Network request failed] at node_modules/whatwg-fetch/dist/fetch.umd.js:535:17 in setTimeout$argument_0
Here is how I set up the backend
import { Application } from "https://deno.land/x/oak/mod.ts";
import { oakCors } from "https://deno.land/x/cors/mod.ts";
import { APP_HOST, APP_PORT } from "./config.ts";
import router from "./routes.ts";
import _404 from "./controllers/404.ts";
import errorHandler from "./controllers/errorHandler.ts";
const app = new Application();
app.use(oakCors());
app.use(errorHandler);
app.use(router.routes());
app.use(router.allowedMethods());
app.use(_404);
console.log(`Listening on port:${APP_PORT}...`);
And how I use fetch to call the API
const App = () => {
const getData = async () => {
const response = await fetch("http://localhost:4000/something");
const data = await response.json();
console.log(data);
};
useEffect(() => {
getData();
}, []);
return (
...
);
};
Note
Some answers on StackOverflow suggest fetching http://[IP_ADDRESS]:4000/something instead of localhost. I've tried that with no luck.
I've verified that the API is working. I can call it successfully in VSCode's Thunder Client and I can also see the data by going to http://localhost:4000 in the browser.
I found a solution to this issue. I'm running my Expo app on a physical device while my server is running on my computer, on localhost. It makes sense that I'm unable to make requests to localhost on my device, because localhost is not running there.
I fixed this issue by using ngrok, a tool that forwards localhost to a cloud URL, and fetching that URL in the app.
Use the local IP assign to your device, like: http://192.168.20.109:port/api/x
find the local IP using the command "ipconfig" in windows or ifconfig in linux

Stripe Connect Account - return_url - Link back to Expo application

I'm on-boarding users onto Stripe connect. My node server generates a temporary HTTPS URL so that customers can sign on. According to their docs I need to provide a URL for when they complete the application.
https://stripe.com/docs/api/account_links/create#create_account_link
I have an Expo application. The user will open up the URL in their browser. However when they complete their application I would like them to go back to Expo App. If I try to use expo://MYAPP/ as the return_url, Stripe does not recognize the URL schema.
Does anyone have an idea how i can return the user back into my application after completing their on-boarding done via the browser?
For anyone one out there who runs into this post, this is was my solution. Your app has to link to a website. I am using Expo, but this is the React code to generate the link.
import * as WebBrowser from 'expo-web-browser';
import * as Linking from 'expo-linking';
const openPage = async () => {
try {
const result = await WebBrowser.openAuthSessionAsync(
`${url}?linkingUri=${Linking.createURL('/?')}`,
);
let redirectData;
if (result.url) {
redirectData = Linking.parse(result.url);
}
setstate({ result, redirectData });
} catch (error) {
console.log(error);
}
};
When you load the site, make sure to pass the URL that was generated from your backend
Backend code:
stripe.accountLinks
.create({
type: 'account_onboarding',
account: accountID,
refresh_url: `https://website.com/refresh`,
return_url: `https://website.com/return`,
})
When the user has the site open, have a button that redirects to the stripe URL.This is how i thought it went first
App -> Stripe connect
instead you have to approach it like this
App -> Website -> Stripe connect

Unifying localhost dev api server access for expo app across Android, IOS, and web?

I'm setting up a simple React Native learning app for several students on Expo, that also talks to an API server the student is learning to code.
The student's API server is run via node server.js, and serves on localhost:3000 on the student's machine. It has nothing to do with expo.
I want students to be able to run their app via any of expo start --android, expo start --ios, or expo start --web, on the same machine that runs their API server. Each student runs from home on a different home wifi network, and doesn't necessarily know the ins and outs of ip addresses or networking.
When using expo start --web, we get CORS exceptions, unless we use the custom webpack.config.js work around (first create webpack.config.js via https://docs.expo.io/guides/customizing-webpack/, then put this in webpack.config.js):
const createExpoWebpackConfigAsync = require('#expo/webpack-config');
module.exports = async function(env, argv) {
const config = await createExpoWebpackConfigAsync(env, argv);
if (config.mode === 'development') {
config.devServer.proxy = {
'/**': {
target: {
host: 'localhost',
protocol: 'http:',
port: 3000,
},
secure: false,
changeOrigin: true,
logLevel: 'info',
},
};
}
return config;
};
This is great, because we can make api calls to ./end/point without knowing the student's ip address, and the webpack devServer launched by expo-cli effectively proxies around to http://localhost:3000/end/point on the student's development machine.
Meanwhile, for iOS and Android, I've found this snippet:
import Constants from "expo-constants";
const { manifest } = Constants;
const SERVER_URL = "http://"+manifest.debuggerHost.split(`:`).shift().concat(`:3000`)+"/";
and then using SERVER_URL when using fetch().
But, we're missing a unified solution that works agnostic of which environment we're in (web, ios, or android). The webpack proxy only appears to be on and work when using the expo web client (expo-cli doesn't launch webpack for ios or android), and the 2nd option (A) doesn't work out of the box on web and (B) would trigger a CORS exception anyway.
How can I elegantly write one bit of code, or otherwise set up the project for the students, so that (A) they don't need to know their dev machine's ip address, or what that means and (B) it will work regardless of whether they're in the web, android, or ios expo client?
Don't like this as an answer and would prefer someone who knows better to point out better, but this is what I ended up using that seems to work, at least in development:
// Some chatter that Contants.manifest needs to come from a different package?
import Constants from "expo-constants";
const { manifest } = Constants;
const SERVER_URL = (() => {
// TODO - put a "prod" api server somewhere
// Android / IOS - no CORS issue.
if (!!manifest.debuggerHost) {
return "http://"+manifest.debuggerHost.split(`:`).shift().concat(`:3000/`);
}
// Expo Web client, making use of webpack.config.js (see original question) for devServer proxy.
else {
return "./";
}
})();
...
fetch(SERVER_URL + 'some_endpoint/').then(...)

Axios GET request resulting in CORS error

I'm working on a VueJS app, and I want to use the Yahoo! Shopping API (documentation: https://developer.yahoo.co.jp/webapi/shopping/shopping/v1/itemsearch.html) to fetch products using their barcode. However, I keep getting a CORS error and I'm not sure why, or what I can do to make it work. My code is as follows:
data() {
return {
appId: 'dj00aiZpPUQ4RTBUUTVSNUs3TyZzPWNvbnN1bWVyc2VjcmV0Jng9NTI-',
apiUrl: 'https://shopping.yahooapis.jp/ShoppingWebService/V1/json/itemSearch'
}
}
...
axios.get(this.apiUrl, {
params: {
appid: this.appId,
jan: 4589707054951
}
})
.then((response) => {
console.log(response);
})
.catch((error) => {
alert(error)
})
The specific error I get is this:
Access to XMLHttpRequest at
'https://shopping.yahooapis.jp/ShoppingWebService/V1/json/itemSearch?appid=dj00aiZpPUQ4RTBUUTVSNUs3TyZzPWNvbnN1bWVyc2VjcmV0Jng9NTI-&jan=4589707054951'
from origin 'https://0.0.0.0:8080' has been blocked by CORS policy: No
'Access-Control-Allow-Origin' header is present on the requested
resource.
What can I do to make this work? So far the only way it works is using the CORS Chrome extension, but that's naturally just for testing.
Thanks a lot.
The server/api owner needs to send this in his response header:
Or if you have a server settings panel or something, make sure to add the domain from where you are making the request.
Access-Control-Allow-Origin: 'your-domain-here'.
Please read more at: https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS
I got the same error. I solved it in the following manner.
This error occurs because we are tryign to access the data hosted on a different server. CORS issue is a browser issue where a certain browser does allow you to access the contents hosted on a different or a virtual server. If you observe the app that you are running on is on the local-host (https://0.0.0.0:8080) and trying to access the data hosted on https://shopping.yahooapis.jp/ShoppingWebService/V1/json/itemSearch. You can solve this problem simply by adding in a few lines of code in your vue application.
Step 1:
Create a new file called vue.config.js in your root directory of the vue application, that is beside your package.json file. Add the following code in your vue.config.js file:
module.exports = {
devServer:{
proxy: "https://shopping.yahooapis.jp"
}
}
Note: https://shopping.yahooapis.jp would be your base url.
Step 2:
Now, go back to your code in data(). Replace the domain name/base url of the apiUrl with https://0.0.0.0:8080. that is now your apiUrl would be https://0.0.0.0:8080/ShoppingWebService/V1/json/itemSearch.
data() {
return {
appId: 'dj00aiZpPUQ4RTBUUTVSNUs3TyZzPWNvbnN1bWVyc2VjcmV0Jng9NTI-',
apiUrl: 'https://0.0.0.0:8080/ShoppingWebService/V1/json/itemSearch'
}
}
Step 3:
Restart your application. Eg, npm run serve.
I found another solution which worked without creating a proxy server or a mock server. You can disable the security settings for accessing cross origin apis on your web browser.
You can disable the CHROME security settings for accessing apis out of the origin by typing the below command on the terminal:
/Applications/Google\ Chrome.app/Contents/MacOS/Google\ Chrome --user-data-dir="/tmp/chrome_dev_session" --disable-web-security
After running the above command on your terminal, a new chrome window with security settings disabled will open up. Now, run your program (npm run serve / npm run dev) again and this time you will not get any CORS error and would be able to GET request using axios.
Hope this helps!