0

I am having a problem where I am trying to fetch the data from the coordinates stored from the database and display them to the webpage. I am using mapbox as my map display and instead of actual coordinates, it should be the landmark or the nearest location pointed on the map

const [projectCard, setProjectCard] = useState([]);
const geocodeJson = "https://api.mapbox.com/geocoding/v5/mapbox.places/"
const apiKey = "myAPIKey"

useEffect(() => {
    instance.get("/getAvailableProjects").then((response) => {
        setProjectCard(response.data); // <-- retrieve from the database
    });
}, []);

return (
    <div>
        {projectCard.map((val) => {
            let location = ""; // <-- location string stored here

            let coordinate = val.PROJECT_LOCATION;
            const comma = coordinate.indexOf(',');
            const longitude = coordinate.substring(comma + 1);
            const latitude = coordinate.substring(0, comma);
            const url = `${geocodeJson}${longitude},${latitude}.json?${apiKey}`

            const getLocation = () => {
                try {
                    fetch(url).then(response => response.json()).then(data => {

                    location = `${data.features[0].text}, ${data.features[0].context[1].text}, ${data.features[0].context[2].text}, ${data.features[0].context[3].text}`
                    console.log("fetch: " + location) // <-- fetched data displayed at the console as [landmark, city, province]
                    })
                } catch (error) {
                    console.log(error)
                }

                console.log(location) // <-- the output here displayed on the console is empty (this was printed out first on the console)
                return location;
            }

            return(
                <p class="card-text">
                    Location: <br />{getLocation()} 
                </p>
            )
        )}
    </div>
)

I also want to point out that what I have observed when checking at the console is that the "empty" string displays first before the fetched data.

I am still new to using react and I want to know where I went wrong.

Irving Real
  • 25
  • 1
  • 8
  • Does this answer your question? [How to return the response from an asynchronous call](https://stackoverflow.com/questions/14220321/how-to-return-the-response-from-an-asynchronous-call) – David Mar 05 '22 at 16:18
  • Aside from the problem of returning a response from an asynchronous call... You already have in this code an example of what you should be doing. Create a *state value* for "location". Instead of trying to *return* the location, update the state value with the fetched value. Then in the rendered markup you would use that state value. Fetch from the API in a `useEffect` rather than directly in the rendered markup. All of this is just like what you're already doing with `projectCard`. – David Mar 05 '22 at 16:21
  • Wouldn't that make that an infinity loop scenario when putting a state variable inside rendering? Also since the details of the coordinates are from the projectCard, I couldnt be able to execute – Irving Real Mar 05 '22 at 16:36
  • Why would rendering a state value create an infinite loop? *Updating* state when rendering would do that, but not *viewing* state. So you update the state in the `useEffect` call (just like you already do with another state value) and then render the result. There are a variety of ways to structure this. One could be to create a separate component just for rendering the `projectCard` and perform the API call in that component, then just pass the value the component needs as a prop. Another could be to make the API calls in this component and store the results in an array and render that. – David Mar 05 '22 at 16:41
  • I followed your method to create another component to render the location by passing its url as a prop, and it worked. Thanks – Irving Real Mar 05 '22 at 16:56

0 Answers0