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='© <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='© <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() }, []);