I need to render a list of buttons, in which I have the value coming from one JSON (an url to an object in a server, stored in a local file), and the displayed text from another JSON (the title of the object, which I can only get through a fetch function).
My local JSON looks like this. From it, I need to get the category name and the list of URLS and use them to make a category button (with the value being the list of URLS and the displayed text being the name).
{
"layerUrls": [
{"name": "Education",
"urls": [
"someurl1",
"someurl2"
]},
{"name": "Transports",
"urls": [
"someurl3",
"someurl4"
]
}]
}
Then, I need to get each URL in a button (in the div that matches its category), and I need to get the title of the object linked to each URL from the server. To do all of this, I'm looping through layerUrls to get each category and create the category button. Then, in each loop, I'm mapping the list of URLs to a series of buttons and fetching the names in the server.
generateButtons = (css) => {
// Styling
const style = css
// Get local JSON data
const data = this.props.config.layerUrls
// Init lists
const list = []
const solo = []
// Looping to create a div per category with 1 category button & multiple individual buttons
for (let i = 0; i < data.length; i++) {
let donneesCateg = data[i]
let listURLS = donneesCateg["urls"]
list.push(<div>
{/* Create category buttons */}
<button id={donneesCateg["name"]} className="categ" value={listURLS} onClick={this.selectChangeMultiple}>{donneesCateg["name"]}</button>
{/* Map individual buttons */}
{listURLS.map((item) => {
const featureLayer = new FeatureLayer({
url: item
});
fetch(item + "?f=pjson")
.then(res => res.json())
.then(data => {
const titre = (data.name).replaceAll('_', ' ').substring(1).toLowerCase()
solo.push(<button id={donneesCateg["name"]} className="btn" value={item} onClick={this.selectChangeSingle}>{titre}</button>)
})
return solo
})
}
</div>)
}
// Return the buttons
return (
<div>
<style>
{style}
</style>
{list}
</div>
)
}
The trouble comes from the fetch function I'm using to retrieve the name from the server for each object. I'm pushing the buttons to a list and returning it... Except that it doesn't return anything. I only get the category buttons and that's it. I tried with useEffect with no more success, and I tried to push the name only to the list, but I got an infinite loop.
Can anyone help ? Thanks!
fetch is an asynchronous function, i.e the rest of the code doesn't wait for it to finish executing unless explicitly instructed to do so. Instead of:
fetch(item + "?f=pjson")
.then(res => res.json())
.then(data => {
const titre = (data.name).replaceAll('_', ' ').substring(1).toLowerCase()
solo.push(<button id={donneesCateg["name"]} className="btn" value={item} onClick={this.selectChangeSingle}>{titre}</button>)
})
return solo
use:
const data = await fetch(item + "?f=pjson")
.then(res => res.json())
const titre = (data.name).replaceAll('_', ' ').substring(1).toLowerCase()
solo.push(<button id={donneesCateg["name"]} className="btn" value={item} onClick={this.selectChangeSingle}>{titre}</button>)
return solo
also, be sure to declare the function as async at the top:
generateButtons = async css => { //...