Home > Blockchain >  Can't map data coming from API to render components in React
Can't map data coming from API to render components in React

Time:05-23

I need to render a Leaflet Marker for each location my axios.get returns (it returns an array of objects with each one being a location) but I get two errors when I try to do so:

-"Uncaught TypeError: data.map is not a function"; -"Warning: Can't perform a React state update on a component that hasn't mounted yet. This indicates that you have a side-effect in your render function that asynchronously later calls tries to update the component. Move this work to useEffect instead".

I've tested it with a local sample and it works. The problem is making it use the data retrieved from the promise.

import { useState } from "react"
import { MapContainer, TileLayer, Marker, Popup } from 'react-leaflet'
import { Link } from "react-router-dom"
import axios from "axios"

import "../styles/Map.css"

export default function Map() {
    const [data, setData] = useState({})

    async function getData() {
        await axios.get("http://localhost:8080")
            .then(data => data.json())
            .then(data => setData(data))
            .catch(data => data = "")
    }

    getData()
    
    return (
        <main>
            <MapContainer center={[-23.6334841179179, -46.46843854558035]} zoom={13} scrollWheelZoom={true}>
                <TileLayer
                    attribution='&copy; <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors'
                    url="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png"
                />
                <Marker position={[-23.6334841179179, -46.46843854558035]}>
                    <Popup>{"My house <3"}</Popup>
                </Marker>
                {
                    data && data.map(loc => (
                        <Marker key={data.id} position={[loc.latitude, loc.longitude]}>
                            <Popup>{loc.name}</Popup>
                        </Marker>
                    ))
                }
            </MapContainer>

            <button><Link to="/register">Register new Location</Link></button>
        </main>
    )
}

CodePudding user response:

Please try to use data?.map like this.

import { MapContainer, TileLayer, Marker, Popup } from 'react-leaflet'
import { Link } from "react-router-dom"
import axios from "axios"

import "../styles/Map.css"

export default function Map() {
    const [data, setData] = useState([])

    async function getData() {
        await axios.get("http://localhost:8080")
            .then(data => data.json())
            .then(data => setData(data))
            .catch(data => data = "")
    }

    useEffect(()=>{
       getData();
    },[])
    
    return (
        <main>
            <MapContainer center={[-23.6334841179179, -46.46843854558035]} zoom={13} scrollWheelZoom={true}>
                <TileLayer
                    attribution='&copy; <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors'
                    url="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png"
                />
                <Marker position={[-23.6334841179179, -46.46843854558035]}>
                    <Popup>{"My house <3"}</Popup>
                </Marker>
                {
                    data?.map(loc => (
                        <Marker key={data.id} position={[loc.latitude, loc.longitude]}>
                            <Popup>{loc.name}</Popup>
                        </Marker>
                    ))
                }
            </MapContainer>

            <button><Link to="/register">Register new Location</Link></button>
        </main>
    )
}```

CodePudding user response:

Make the initial default value an array instead of an object.

const [data, setData] = useState([])

An object doesn’t have a map method, but an empty array should.

CodePudding user response:

Try this.

    async function getData() {
        let data = await axios.get("http://localhost:8080")
        data = data?.json();
        if(data !== null) setData(data);
    }
    useEffect(() => { getData() }, []);
  • Related