I have two functions using Axios to make requests of data to an API. Within those functions I also return the response that is received by the API. Both of those functions do use async/await. From my understanding, since Axios returns a promise, I have to await the function calls to unpack the promise and retrieve the data. Am I calling these functions incorrectly? The goal is to use the values returned by these functions to render a React-Leaflet component. However, React it seems to be reading the values as null. My assumption is that when the functions are called within the component, the Promise is being returned instead of the value, even though I am calling the function with await. Below is the code I have so far...
import { MapContainer, TileLayer, Marker, Popup, Circle } from 'react-leaflet';
import mockData from './testData/MOCK_DATA.json'
import axios from 'axios';
import outageData from './testData/outageData.json'
const fillBlueOptions = { fillColor: 'blue' };
async function convertAddressLat(location){//uses the geocodify api to get lat and long of an address
const resp = await axios.get('https://api.geocodify.com/v2/geocode/json?api_key=mykey&q=' + location.outage_street+ ', ' + location.outage_city+ ', Michigan, USA');
return Number(resp.data.response.bbox[1]);
}
async function convertAddressLong(location){
const resp = await axios.get('https://api.geocodify.com/v2/geocode/json?api_key=mykey&q=' + location.outage_street+ ', ' + location.outage_city+ ', Michigan, USA');
return Number(resp.data.response.bbox[2]);
}
/// This returns the actual value I am looking to pass into the react component
(async function(){
let val = await convertAddressLat(outageData.outages[6]);
console.log("Inside function 1: "+val);
})();
//this is still returning a promise. I have tried returning the await and also the method below
console.log("inside function 2: "+(async function(){
let x = await convertAddressLat(outageData.outages[6]);
return x;
})());
function OutageMap() { //This is where the map page will be rendered.
return (
<MapContainer center={[38.89, -77.059]} zoom={13} scrollWheelZoom={true}>
<TileLayer
attribution='© <a href="http://osm.org/copyright">OpenStreetMap</a> contributors'
url="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png"
/>
{outageData.outages.map(mock => (
<Circle center={[
(async function(){
let lat = await convertAddressLat(mock);
return lat;})(),
(async function(){
let long = await convertAddressLong(mock);
return long;})()
]}
pathOptions={fillBlueOptions} radius={200}>
<Popup>{mock.description}</Popup>
</Circle>
))}
</MapContainer>
);
}
export default OutageMap;
I have referenced this post How to return the response from an asynchronous call on how unwrap a promise, but I am confused how I can call the function within the React component.
async
functions always return a Promise. So in this block you're awaiting the convertAddressLat
Promise but the anonymous inline function also returns a Promise.
center={[
(async function(){
let lat = await convertAddressLat(mock);
return lat;})()
One common strategy for rendering asynchronously loaded data is to do the fetching in a useEffect
hook that sets state once the Promise is resolved:
function OutageIndicator ({ outage }) {
const [coords, setCoords] = useState();
useEffect(() => {
async function resolveLocation() {
const resp = await axios.get( ... );
const [lat, lng] = resp.data.response.bbox;
setCoords({ lat, lng })
}
resolveLocation();
}, [outage]);
return !coords ? "Loading" : (
<Circle center={[coords.lat, coords.lng]} />
)
}
function OutageMap () {
return (
<MapContainer center={[38.89, -77.059]} zoom={13} scrollWheelZoom={true}>
{outageData.outages.map(outage => (
<OutageIndicator outage={outage} />
)}
</MapContainer>
)
}