Populate Material dropdow menu from Rest call data - javascript

I want to populate dropdown menu with data from Rest API. I tried this:
<Select id="country-helper">
{array.map((element) => (
<MenuItem value={element.code}>{element.country}</MenuItem>
))}
</Select>
I created this service with Axios:
export interface CountriesDTO {
country?: string;
code: string;
}
import axios, { AxiosResponse } from "axios";
import { CountriesDTO } from "./types";
const baseUrl = "http://localhost:8080/api";
export async function getCountries(): Promise<AxiosResponse<CountriesDTO[]>> {
return await axios.get<CountriesDTO[]>(
`${baseUrl}/merchants/onboarding/countries`
);
}
It's not clear how I can make the call into the React page. I tried this:
useEffect(() => {
const getData = async () => {
getCountries()
.then((resp) => {
console.log(resp.data);
})
.catch((error) => {
console.error(error);
});
};
}, []);
How I can populate the dropdown using the data from GET API call?

Just call your function getData from useEffect, you should also create state array to store your data.
const [array, setArray] = useState<CountriesDTO[]>([]); // <=== create state array
useEffect(() => {
getData(); // <=== call your function
}, []);
const getData = async () => {
getCountries()
.then((resp) => {
setArray(resp.data);
})
.catch((error) => {
console.error(error);
});
};

Related

Fetching multipule endpoints at one return undefined

import React, { useEffect, useState } from "react";
import { endpoint, apiKey } from "../api";
import Container from "../components/layouts/Container";
export default function Movie({ route }) {
const { movieId } = route.params;
const [movieDetails, setMovieDetails] = useState([]);
const [isLoading, setIsLoading] = useState(false);
const urls = [
`${endpoint}/movie/${movieId}?api_key=${apiKey}`,
`${endpoint}/movie/${movieId}/credits?api_key=${apiKey}`,
`${endpoint}/movie/${movieId}/images?api_key=${apiKey}`,
`${endpoint}/movie/${movieId}/reviews?api_key=${apiKey}`,
`${endpoint}/movie/${movieId}/similar?api_key=${apiKey}`,
];
useEffect(() => {
const fetchData = () => {
setIsLoading(true);
Promise.all(
urls.map((url) => {
return fetch(url);
})
)
.then((response) => {
return Promise.all(response.map((res) => res.json()));
})
.then((data) => {
setMovieDetails(data);
setIsLoading(false);
})
.catch((err) => {
console.log(err);
});
};
fetchData();
}, []);
console.log(movieDetails[0]);
Hello,
I've encountered a problem tha that when i try to fetch the request above when i console.log() it it first returns undefined and then return the desired response.
The response is expected as initially the state is undefined.
During the request also, till the response is unresolved, the process is suspended and the state stays undefined.
A simple solve will be to move the console.log(movieDetails[0]) into the last .then() body or you could write your own Promise resolution functions.

How to a function of another class in React?

I am noob on front-end world and could not find a solution for that I have a MainPanel component and I want to get data by using a service class method. The service class will have multiple functions and I will use them in different places.
Here is MainPanel code:
const [posts, setPosts] = useState({ blogs: [] });
const service = FetchCustomerService;
useEffect(() => {
const fetchPostList = async () => {
let customers = service.getCustomerList;
setPosts({ customers });
console.log(customers);
};
fetchPostList();
}, []);
And I want to create a separate service class for calls to backend:
export class FetchCustomerService {
getCustomerList = () => {
const { data } = await axios(
"https://jsonplaceholder.typicode.com/posts"
);
return data;
}
getAnotherFunction = () => {
}
}
export default FetchCustomerService;
How can I call service class method from MainPanel? There are some examples like giving the service class into main panel as props but isn't it possible to just call it like a Java class object etc calling like:
FetchCustomerService.getCustomerList();
You don't need a class for that, just export the functions you need from the file:
export async function getCustomerList() {
const { data } = await axios(
"https://jsonplaceholder.typicode.com/posts"
);
return data;
}
export function getAnotherFunction(){
...
}
import { getCustomerList } from 'yourFile';
...
useEffect(() => {
const fetchPostList = async () => {
const customers = await getCustomerList();
setPosts({ customers });
};
fetchPostList();
}, []);

How can I re-fetch an API automaticaly until data is fetched succesfully?

I have an API that sometimes doesn't work. I would like for the App to refetch automaticaly if this happens until it gets the necessary data. How can I do that? I'm thinking that maybe this could be done by using a dependency on the useEffect hook, but I'm not clear on how to do it.
Lets say we have this App component
export default function App() {
const [data, setData] = useState([])
useEffect(() => {
getData({ setData })
}, [])
return [
<h3>
{data[0].title}
</h3>
]
}
And this API component
const url = 'https://some-random-url.com/whatever-api'
export default function getData({ setData }) {
axios.get(url)
.then((response) => {
let dataArray = response.data.results
setData(dataArray)
})
.catch((error) => {
console.log(error)
})
}
If you were to do it with useEffect, you could pass an error counter state to getData function and increase it on error or empty data.
Then add to your useEffect dependency array to refetch.
But this certainly implies that you have to think further what you are wanting to do after a certain amount of retries, to avoid an infinite loop.
export default function App() {
const [data, setData] = useState([])
const [errCount, setErrCount] = useState(0)
useEffect(() => {
getData({ setData, errCount, setErrCount })
}, [errCount])
return [
<h3>
{data[0].title}
</h3>
]
}
And this API component
const url = 'https://some-random-url.com/whatever-api'
export default function getData({ setData, errCount, setErrCount }) {
axios.get(url)
.then((response) => {
let dataArray = response.data.results
setData(dataArray)
!dataArray.length && setErrCount(errCount+1);
})
.catch((error) => {
setErrCount(errCount+1);
console.log(error)
})
}

How do you return function results to a React Component?

Seems easy but I can't figure it out, how would you return the results from a function that's being imported to a component?
I get the correct results when i console log them from the .then() but can't seem to return them to the component.
example:
functions.js
export const getFeatures = (e) => {
let features = Client.getEntries({
content_type: '###',
'fields.type': `${e}`
})
.then(response => {
return response.items;
})
.catch(console.error)
}
Component.js
import {getFeatures} from './functions.js'
const App = () => {
let x = getFeatures('home');
console.log(x)
return ( ... )
// expecting the array response [{},{},{}, .. etc], but getting undefined instead
}
getFeatures doesn't return anything, you should change it to return its promise:
export const getFeatures = (e) => {
return Client.getEntries({
content_type: '###',
'fields.type': `${e}`
})
.then(response => {
return response.items;
})
.catch(console.error)
}
then at App add a features state, that will get updated when you call getFeatures on mount stage called by useEffect:
import { useState, useEffect } from 'react'
import {getFeatures} from './functions.js'
const App = () => {
// create a features state
const [features, setFeatures] = useState([])
// on mount call 'getFeatures'
useEffect(() => {
getFeatures('home')
.then(setFeatures) // chain returned promise and pass setFeatures to update features
}, []) // add empty array to tell to run the code on mount only
// do some mapping with features, this is for example purpose
// remember to add an unique key to each feature
return ( features.map(feature => {
return <div key={feature.id}>{feature.name}: {feature.realease}</div>
}))
}
getFeatures('home') will return undefined instead of response.items in your code.
Try this:
// functions.js
export const getFeatures = async (e) => {
const resp = await Client.getEntries({
content_type: '###',
'fields.type': `${e}`
})
return resp.items;
}
// App.js
import {getFeatures} from './functions.js'
const App = () => {
getFeatures('home').then(x => {
console.log(x);
// do something else
});
return ( ... )
}

"Promise{<pending>}" in console instead of a value

I am trying to import a function that fetches data from an api in a file (.src/api/index.js) to my App.js (.src/App.js).
.src/api/index.js
import axios from 'axios';
const url = 'https://covid19.mathdro.id/api';
export const fetchData = async () => {
try {
const res = await axios.get(url);
return res;
} catch (error) {}
};
.src/App.js
import React, { useEffect } from 'react';
import { fetchData } from './api';
const App = () => {
useEffect(() => {
const data = fetchData();
console.log(data);
}, []);
return <div></div>;
};
export default App;
};
I am getting a Promise{<pending>} in my console when I run this but I am trying to get the values in the object.
fetchData() is an async function, and you need to await it like so:
const data = await fetchData();
Then, the useEffect must also be an async function:
useEffect(async () => {
const data = await fetchData();
console.log(data);
}, []);
You are not waiting for promise to resolve. use await or .then. If you wanna use await, make callback function of useEffect async function.
const App = () => {
useEffect(async () => {
const data = await fetchData();
console.log(data);
}, []);
return <div></div>;
};
Other approach is to use .then.
const App = () => {
useEffect(async () => {
const data = fetchData().then((data) => console.log(data));
}, []);
return <div></div>;
};

Categories