Dynamic file names in react native require() - node.js

We're working on an app that will allow users to store templates with images on them, and pull those templates up later. This is for an AR environment using Viro on React Native.
We're trying to dynamically load an image into the component, and receiving errors when we require the filepath, which has been set to a variable:
const exampleUri = '/some/uri'
render() {
return(
<Viro3DObject
source={require(exampleUri)}
/>)
}
The URI for the source prop has to be dynamic, as the URIs are pulled from a Database.
We've tried storing the entire request in the database (in models/element.js):
const Sequelize = require('sequelize');
const db = require('../db');
const Element = db.define('element', {
sourceViro3DObject: {
type: Sequelize.STRING
}
});
sourceViro3DObject: `require('../../assets/emoji_heart/emoji_heart.vrx')`
When we called it in the React Native class component:
getObjectData = async () => {
try {
const {data} = await axios.get(`/api/elements/${this.props.elementId}`)
this.setState({sourceViro3DObject: data.sourceViro3DObject})
} catch (err) {
console.log(err)
}
}
async componentDidMount() {
await this.getObjectData()
}
But this simply sets state.sourceViro3DObject to a string:
'require('../../assets/emoji_heart/emoji_heart.vrx')'
We've tried setting the filepath directly to state as a string:
state.sourceViro3DObject = '../../assets/emoji_heart/emoji_heart.vrx'
and then call require on it:
require(this.state.sourceViro3DObject)
and received the following error:
Invalid prop `source` supplied to `Viro3DObject`
We've seen recommendations of storing the URIs in an object, but that can't work for us as we don't know what image is going to be used until it's pulled from the database. We can't hard-code them anywhere.
We'd appreciate any help with this!

Related

How does one secure api keys on sveltekit 1.0

I am using ghost, i made an integration and i would like to hide the api key from the front-end. I do not believe i can set restrictions on the ghost cms (that would also work). And i do believe so +page.js files are run on the browser also, so im a little confused on how to achieve this?
The interal sveltekit module $env/static/private (docs) is how you use secure API keys. Sveltekit will not allow you to import this module into client code so it provides an extra layer of safety. Vite automatically loads your enviroment variables from .env files and process.env on build and injects your key into your server side bundle.
import { API_KEY } from '$env/static/private';
// Use your secret
Sveltekit has 4 modules for accessing enviroment variables
$env/static/private (covered)
$env/static/public accessiable by server and client and injected at build (docs)
$env/dynamic/private provided by your runtime adapter; only includes variables with that do not start with the your public prefix which defaults to PUBLIC_ and can only be imported by server files (docs)
$env/dynamic/public provided by your runtime adapter; only includes variables with that do start with the your public prefix which defaults to PUBLIC_ (docs)
You don't need to hide the key.
Ghost Content API Docs:
These keys are safe for use in browsers and other insecure environments, as they only ever provide access to public data.
One common way to hide your third-party API key(s) from public view is to set up proxy API routes.
The general idea is to have your client (browser) query a proxy API route that you provide/host, have that proxy route query the third-party API using your credentials (API key), and pass on the results from the third-party API back to the client.
Because the query to the third-party API takes place exclusively on the back-end, your credentials are never exposed to the client (browser) and thus not visible to the public.
In your use case, you would have to create 3 dynamic endpoint routes to replicate the structure of Ghost's API:
src/routes/api/[resource]/+server.js to match /posts/, /authors/, /tags/, etc.:
const API_KEY = <your_api_key>; // preferably pulled from ENV
const GHOST_URL = `https://<your_ghost_admin_domain>/ghost/api/content`;
export function GET({ params, url }) {
const { resource } = params;
const queryString = url.searchParams.toString();
return fetch(`${GHOST_URL}/${resource}/?key=${API_KEY}${queryString ? `&${queryString}` : ''}`, {
headers: {
'Accept-Version': '5.0' // Ghost API Version setting
}
});
}
src/routes/api/[resource]/[id]/+server.js to match /posts/{id}/, /authors/{id}/, etc.:
const API_KEY = <your_api_key>; // preferably pulled from ENV
const GHOST_URL = `https://<your_ghost_admin_domain>/ghost/api/content`;
export function GET({ params, url }) {
const { resource, id } = params;
const queryString = url.searchParams.toString();
return fetch(`${GHOST_URL}/${resource}/${id}/?key=${API_KEY}${queryString ? `&${queryString}` : ''}`, {
headers: {
'Accept-Version': '5.0' // Ghost API Version setting
}
});
}
src/routes/api/[resource]/slug/[slug]/+server.js to match /posts/slug/{slug}/, /authors/slug/{slug}/, etc.:
const API_KEY = <your_api_key>; // preferably pulled from ENV
const GHOST_URL = `https://<your_ghost_admin_domain>/ghost/api/content`;
export function GET({ params, url }) {
const { resource, slug } = params;
const queryString = url.searchParams.toString();
return fetch(`${GHOST_URL}/${resource}/slug/${slug}/?key=${API_KEY}${queryString ? `&${queryString}` : ''}`, {
headers: {
'Accept-Version': '5.0' // Ghost API Version setting
}
});
}
Then all you have to do is call your proxy routes in place of your original third-party API routes in your app:
// very barebones example
<script>
let uri;
let data;
async function get() {
const res = await fetch(`/api/${uri}`);
data = await res.json();
}
</script>
<input name="uri" bind:value={uri} />
<button on:click={get}>GET</button>
{data}
Note that using proxy API routes will also have the additional benefit of sidestepping potential CORS issues.

Query parameters not received from deep linking - react native(expo) and node js

I am using openAuthSessionAsync to do a call to my backend and sending the url for deep linking
I am redirected back successfully to my app but i don't get query parameters that i send from backend with deep link
My react native app side:
const experiment = async()=>{
try{
let result = await WebBrowser.openAuthSessionAsync(`http://myaddress :3901/api/testig?linkingUri=${Linking.createURL(
"/?",
)}`,);
console.log(result)
}catch(errr){
console.log(errr)
}
}
My node js side:
router.get("/testig",(req,res)=>{
url = req.query.linkingUri
**//url is exp://myaddress:19000/--/?**
res.redirect(url+"?authToken=abc123")
})
I have also tried hard coding the url in backend but it only opens app back but with no parameters
And in my react native side in console i get this:
Object:{
"type":"dismiss",
}
UPDATE: Solved it by setting up eventListener for LINKING as follows
const handleDeepLink = (event)=>{
let data = Linking.parse(event.url)
setdata(data)
if(JSON.parse(data.queryParams.isSuccessful) == true)
{
props.navigation.navigate("thankyou")
}
}
React.useEffect(()=>{
Linking.addEventListener("url",handleDeepLink)
return(()=>{
Linking.removeEventListener("url")
})
},[])
use trycarch in the block to see errors and use var url
code lookslike
router.get("/testig",(req,res)=>{
try {
var url = req.query.linkingUri
return res.redirect(url+"?authToken=abc123")
} catch (e) {
console.log(e)
}
})

Pulling Data From Node.js Rest Api Into React with axios

I am New to react, Node.js so I apologize if this is simple. I have been trying to pull Data From A Node.js Api Running Express into a React Component with Axios. I have tried many different ways and have searched for a solution with no luck. I am unable to access the Id as well as the ProductName
JSON DATA
{"Results":
[
{"id":4,"productName":"Flap Disc"}, {"id":5,"productName":"Fiber Disc"}
]
}
For whatever reason I am unable to Access the data inside these Objects.
CODE
export default function Parent () {
const [products, setProducts] = React.useState('');
const url = 'http://localhost:3040/';
React.useEffect(()=>{
async function getProduct(){
const response = await axios.get(`${url}`);
const a = (response.data.Results)
setProducts(a.map((item)=>
{item}
))
}
getProduct()
}, [])
return(
<div>
{
console.log(products)
}
</div>
)
}
Logging out inside JSX won't do anything. What you want to do is map over the data and display it as a component. Change your return to something more like this
return (
<div>
{products?.map((product) => <p>{product.name}<p>)
</div>
)
You should also change the default value fo products from an empty string to an empty array
const [products, setProducts] = React.useState([])

Shopify API Node/Express Cannot read properties of undefined (reading 'Rest')

Just starting off with Shopify, and trying to get an order. Following the Shopify API documentation, here is my code:
const Shopify = require('#shopify/shopify-api');
const client = new Shopify.Clients.Rest('my-store.myshopify.com',
process.env.SHOPIFY_KEY);
module.exports.getShopifyOrderById = async (orderId) => {
return await client.get({
path: `orders/${orderId}`,
});
}
I get the following error when I execute this code:
TypeError: Cannot read properties of undefined (reading 'Rest')
Can't seem to figure out what the issue is.
You need to use Object destructing to get the Shopify object or use default export like below.
const { Shopify } = require('#shopify/shopify-api');
const client = new Shopify.Clients.Rest('my-store.myshopify.com',
process.env.SHOPIFY_KEY);
OR
const Shopify = require('#shopify/shopify-api').default;
const client = new Shopify.Clients.Rest('my-store.myshopify.com',
process.env.SHOPIFY_KEY);
OR
const ShopifyLib = require('#shopify/shopify-api');
const client = new ShopifyLib.Shopify.Clients.Rest('my-store.myshopify.com',
process.env.SHOPIFY_KEY);
This has to do with how ES6 modules are emulated in CommonJS and how you import the module. You can read about that here.

How can I import an image from the express server to the client (in React)

I'm trying to show an image in react, which is neither a local image (in the client) nor an external image from the web but an image that is in the node.js express server (and I don't want to call it as if it was an external image, because the domain could change and it just doesn't seem right).
I know I can't just import it like I do with a local image in the client because we're speaking about different localhosts. I did try this:
loadImage = async (imageUrl) => {
const response = await fetch(`/api/images/${imageUrl}`);
const data = await response.json();
this.setState({ image: data });
}
componentDidMount() {
const { imageUrl } = this.props;
try {
this.loadImage(imageUrl);
} catch(error) {
console.log("Hay un error: " + error);
}
}
render() {
const { image } = this.state;
return(
<div>
<div>
<img alt="dontknowyet" className="blog-list-image" src={image} // and so on...
{image} does receive the correct path, but the image won't load and the console throws this error:
Not allowed to load local resource: file:///C:/Users/Dafna/Desktop/adrian/proyectos/esteticand/img/t4.jpg
So how can I make it work? and in case that I need to import the image file instead of just the link, how can I do that? (I can't update the state with an image...)
In order to access the path of the image it has to be done through the express server.
For example, if the (backend) server is running on port 4500 and the image is in a folder called images, and the express variable is called app, in the server file you have to use:
app.use(express.static('images'));
and then the image can be accessed in http://localhost:4500/nameoftheimage.jpg.
Do you have the api running on the same port as the React app?
You usually would make them run on different ports. Maybe it's got something to do with it.

Resources