Hi here is what is working and what i need to change.
I have under my SCR folder a data folder for testing purposes in which there are many json files.
I actually have many react list component which I want to change to only one generic component by passing the json filename and path instead of hardcoding it.
this works
import React from 'react'
import { Link } from 'react-router-dom'
import * as s from '../../components/Shared/ListCards.styles'
import ListData from '../../data/user.json'
const ListCards = () => {
const listJSX = ListData.map((user, index) => {
return ()
I would like to change
import ListData from '../../data/user.json'
to
import ListData from 'path/filename.json'
path and filename is stored in localStorage
localStorage.getItem('colName')
You could use dynamic imports
const { default: ListData } = await import('path/filename.json');
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/import#dynamic_imports
You may want to considering using the fetch api instead, if the path stored inside your local storage relates to a URL:
const ListCards = () => {
const { listData, setListData } = useState([]);
(async () => {
const response = await fetch('/urlpath/filename.json')
const data = await response.json()
setListData(data)
})();
const listJSX = listData.map((user, index) => {
return ()
Related
I have created a React app that allows users to add images to the cart. Each image is contained in the { cartItems } array which is controlled using Redux. When the user clicks the button, I want a zip file generated with all the images that are in the cart. I think I should be using the jszip library, but can't seem to figure it out. Below is a snippet of my code.
import React, { useState } from 'react'
import { useSelector } from 'react-redux'
import { motion } from 'framer-motion'
import JSZip from 'jszip'
export default function Cart() {
const { cartItems } = useSelector((state) => state.cart)
const handleZipDownload = () => {
}
return (
<div className='pt-16 relative px-12' id='grid-container'>
<h1 className='text-5xl mb-16 text-center' id='grid-header'>
Shopping Cart
</h1>
<button onClick={handleZipDownload}>download images</button>
</div
)
It's doable, I did the same for some .json files.
import JSZip from 'jszip'
import { saveAs } from 'file-saver'
const { cartItems } = useSelector((state) => state.cart)
const handleZipDownload = async () => {
const zip = new JSZip()
cartItems.forEach(img => {
zip.file(img.name, imgData, { base64: true });
})
const zipped = await zip.generateAsync(
{
type: 'blob',
comment: 'Optional comment for example your website URL',
})
saveAs(zipped, 'archive file name')
}
You just need to figure out how to pass imgData depending on how you save/access images in the cart. You most likely have their URLs, in that case use fetch() get the image blob then use it here. If you do end up passing blob as 2nd argument of zip.file then as 3rd argument pass
{ binary: true }
See more
https://stackoverflow.com/a/50248437/8833279
https://stuk.github.io/jszip/documentation/api_jszip/file_data.html
All I wanna do is be able to call logic from my geolocationApi file into my react-native components whenever I want, NOT LIKE A HOOK but normal async functions, I'm using a custom hook in the geolocationApi file I'm importing though! (custom hooks handles mobx state updates)
I want to call it like this in my functional components (plain and easy):
import geolocationApi from '#utils/geolocationApi.js'
const getCoords = async () =>
{
let result = await geolocationApi().requestLocationPermissions(true);
};
My geolocationApi file where I have a bunch of functions about geolocation I don't want to crowd my components with.
#utils/geolocationApi.js
import _ from 'lodash';
import Geolocation from 'react-native-geolocation-service';
import { useStore } from '#hooks/use-store';
const geolocationApi = () => {
//Custom hook that handles mobx stores
const root = useStore();
const requestLocationPermissions = async (getCityName = false) =>
{
const auth = await Geolocation.requestAuthorization("whenInUse");
if(auth === "granted")
{
root.mapStore.setLocationEnabled(true);
let coords = await getMe(getCityName);
return coords;
}
else
{
root.mapStore.setLocationEnabled(false);
}
};
const getMe = async () =>
{
Geolocation.getCurrentPosition(
async (position) => {
let results = await onSuccess(position.coords);
return results;
},
(error) => {
console.log(error.code, error.message);
},
{ enableHighAccuracy: true, timeout: 15000, maximumAge: 10000 }
);
};
/*const onSuccess = async () => {}*/
};
export default geolocationApi;
This can't be that hard!
If I remove export default geolocationApi and instead add export const geolocationApi at the top I get:
geolocationApi.default.requestLocationPermissions is not a function
You cannot use hooks outside React components. You can pass down the state to your function
import geolocationApi from '#utils/geolocationApi.js'
const getCoords = async (root) =>
{
let result = await geolocationApi(root).requestLocationPermissions(true);
};
Then instead of using useStore()
import _ from 'lodash';
import Geolocation from 'react-native-geolocation-service';
import { useStore } from '#hooks/use-store';
// pass the root from top
const geolocationApi = (root) => {
// your logic
return {
requestLocationPermissions,
getMe
}
}
Then somewhere in your component tree, ( an example with useEffect )
import getCoords from 'path'
const MyComp = () => {
const root = useStore();
useEffect(() => {
getCoords(root)
}, [root])
}
As you said, geolocationApi is a regular function, not a React component/hook. So, it isn't inside the React lifecycle to handle hooks inside of it.
You can use the Dependency Injection concept to fix it.
Make geolocationApi clearly dependent on your store.
const geolocationApi = (store) => {
Then you pass the store instance to it.
const getCoords = async (store) =>
{
let result = await geolocationApi(store).requestLocationPermissions(true);
};
Whoever React component calls the getCoords can pass the store to it.
//...
const root = useStore();
getCoords(root);
//...
I have a React component (also using TypeScript) that returns a photo to its parent component:
import React, { useEffect, useState } from "react";
import axios from "axios";
export const Photo = () => {
const [image, setImage] = useState<Image[]>([]);
// Backend API
const proxyUrl = "http://localhost:3001";
const api = "/photo";
interface Image {
src: string;
}
useEffect(() => {
(async function callAPI() {
axios
.get<Image>(proxyUrl + api)
.then((response) => {
setImage([
{
...response.data,
},
]);
})
.catch((error) => console.log(error));
})();
}, []);
if (image.length === 0) return <span>loading Image...</span>;
return <img src={String(image[0])} />;
The goal is to get an artist's profile picture from my backend. The only way that I can save the image in state is by using the spread operator, and when I do so, it SPREADS the URL - placing each taking each letter and placing it as a value in an object (see the screenshot below).
When I remove the spread operator, I get lots of errors. I need a way to retrieve the photo URL without breaking it up so that I can return and view it. Perhaps by changing the way I defined the interface? Or by setting up state differently?
Image of the URL being spread
first of all modify your useState like this :
const [image, setImage] = useState<String>([]);
and data is fetched you should setState like this :
setImage(response.data)
and delete Image from your get function type.
your return :
return <img src={image)} />;
With the help of the comments above by mortezashojaei, I was able to tweak the component and finally able to get it to work as intended. Adding the code here in case anyone's interested.
import React, { useEffect, useState } from "react";
import axios from "axios";
export const Photo = () => {
const [image, setImage] = useState<string>("");
// Backend API
const proxyUrl = "http://localhost:3001";
const api = "/photo";
useEffect(() => {
(async function callAPI() {
axios
.get(proxyUrl + api)
.then((response) => {
setImage(response.data);
console.log("RESPONSE.DATA");
console.log(response.data);
})
.catch((error) => console.log(error));
})();
}, []);
console.log("Image (state): ");
console.log(image);
if (!image) return <span>loading Image...</span>;
return <img src={image} />;
};
I'm having trouble figuring out how I can make a request to an API based on the response from another request. I'm making a request to an API and extracting the IP address from the response.
Then I want to make another request to a different API using the IP address as input to the 2nd API. When I try the code below I get the error React Hook "useSwr" cannot be called inside a callback. React Hooks must be called in a React function component or a custom React Hook function
I'm using React, TypeScript and SWR. I had this working with a simple JavaScript code but I think I'm getting confused with React/Typescript/SWR here. Is there a better way to accomplish what I'm trying to do?
import React, {FC} from 'react';
import useSwr from 'swr';
const fetcher = (...args: Parameters<typeof fetch>) => fetch(...args).then(response => response.json());
const Webmap: FC = () => {
const validatorUrl = 'http://url1.com';
const ipInfoUrl = 'http://url2.com';
const {data, error} = useSwr(validatorUrl, fetcher);
const validatorData = data && !error ? data : [];
if (validatorData.results != null) {
validatorData.results.forEach(u => {
const ipAddress= u.ip_address
console.log(ipAddress)
// This is where I want to make another request. I want to feed ipAddress to ipInfoUrl
const {data, error} = useSwr(ipInfoUrl, fetcher);
const ipData = data && !error ? data : [];
});
}
Your are breacking a golden rule from hook definition:
https://reactjs.org/docs/hooks-rules.html
Here: https://swr.vercel.app/docs/conditional-fetching#dependent
import React, {FC} from 'react';
import useSwr from 'swr';
const fetcher = (...args: Parameters<typeof fetch>) => fetch(...args).then(response => response.json());
const Webmap: FC = () => {
const validatorUrl = 'http://url1.com';
const ipInfoUrl = 'http://url2.com';
const { data: validationData, error: validationError } = useSwr(validatorUrl, fetcher);
const { data: ipData, error: ipError } = useSwr(() =>
// this request wont be called until validationData succeeds
// use a data from validationData, example:
ipInfoUrl + '?ip=' validationData.results.ip_address,
fetcher
);
console.log(ipData);
I wanted to import data(get users) from https://docs.github.com/en/rest/reference/users#list-users
the code in JS file(reactjs) is like
const { Octokit } = require("#octokit/rest");
const octokit = new Octokit();
async function myAsyncMethod() {
const result = await octokit.request("GET /users");
console.log(result.data);
}
myAsyncMethod();
but in the browser, didn't show anything, it's the correct way to get the data?
It all depends on where do you want to call this piece of code.
For instance, let's say that you need to call it as soon as the component that you're going to display is rendered. In that case, you will need to use the useEffect hook, and call your function from there.
See the following piece of code (I'm using the component App just for the example).
import React, { useEffect } from "react";
const { Octokit } = require("#octokit/rest");
export default function App() {
const octokit = new Octokit();
useEffect(() => {
getGithubUsers();
});
async function getGithubUsers() {
const result = await octokit.request("GET /users");
console.log(result.data);
}
return <></>;
}