Reputation: 51
I want to be able to change the center of the react-leaflet map container by clicking the workout container which is an object that has the co-ordinates. I have shared all the states throughout the components using contextApi
//WorkoutData.js
export const WorkoutsData = [
{
id: 1,
coords: {latitude: 56.27360151291927,
longitude:-82.84886256490017},
},
{
id: 2,
coords: {latitude: 49.27360151291927,
longitude: -75.84886256490017},
},
{
id: 3,
coords: {latitude: 39.27360151291927,
longitude: -79.84886256490017},
}
];
//MapLocation.js i have a main.js folder which has all the state variable and all the other components shares the variable using contextapi
import React, { useEffect, useState } from "react";
import "./styles.css";
import { WorkoutsData } from "./WorkoutLocation";
const MapLocation() => {
const [workouts, setWorkouts] = useState(WorkoutsData);
const [changedCoords, setChangedCoords] = useState({latitude: 0, longitude: 0})
const [workoutsClicked, setWorkoutsClicked] = useState(false);
const locateWorkout = (id) => {
setWorkoutsClicked(true)
const findLocation = workouts.find((exercise) => {
return exercise.id === id;
});
setChangedCoords({
latitude: findLocation.coords.latitude,
longitude: findLocation.coords.longitude
})
}
return(
<>
workouts.map((workout) => {
return(
<div key = {workout.id} className = 'workout-info'>
<div className = "workout-details">
<p>{workout.coords}</p>
</div>
</div>
)
})
</>
)
export default MapLocation;
//Map.js i have a main.js folder which has all the state variable and all the other components shares the variable using contextapi
const Map = () => {
const[initialCoords, setInitialCoords] = useState({latitude: 0, longitude: 0})
useEffect(() => {
if (navigator.geolocation) {
navigator.geolocation.getCurrentPosition((position) => {
setInitialCoords({
latitude: position.coords.latitude,
longitude: position.coords.longitude
})
})
}
}, [])
return(
<>
<MapContainer center = {
workoutsClicked !== true ?
[initialCoords.latitude, initialCoords.longitude] :
[changedCoords.latitude, changedCoords.longitude]}
zoom = {20}>
<TileLayer attribution='© <a href="http://osm.org/copyright">OpenStreetMap</a> contributors'
url="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png"/>
</MapContainer>
</>
)
}
export default Map
Upvotes: 3
Views: 2306
Reputation: 6163
MapContainer
props in React Leaflet are immutable (https://react-leaflet.js.org/docs/api-map/#mapcontainer), therefore updating them after the map is initialised will have no effect.
You can use the useMapEvent hook to update the centre of the map when your changedCoords
state changes. First of all define a function:
function UpdateMapCentre(props) {
const map = useMap();
map.panTo(props.mapCentre);
return null;
}
Then add the following as a child of MapContainer
:
<MapContainer ...>
...
<UpdateMapCentre mapCentre={changedCoords} />
</MapContainer>
Because the props passed to MapContainer
are immutable, you no longer need the ternary if statement to set the map centre (updating the map centre is now taken care of using <UpdateMapCentre>
) and can just pass in the initialCoords
.
<MapContainer center={[initialCoords.latitude, initialCoords.longitude]} zoom={20}>
...
</MapContainer>
See this StackBlitz for a working demo. When you click on the latLng of a workout in the list below the map, the changedCoords
state will be updated and the map will pan to the latitude and longitude of the workout.
Upvotes: 3