Design comparison
Solution retrospective
There is a few points I want to share. In order to get the map updated after doing another search, I did some research and found a way with "useReducer", which I would call inside the function that handles the IP search. With that in mind, I would like to know if there is another (recommended/better) way to get that map updated, since the card component already does it without any dedicated function... (that is also something I found weird, the fact that the component will rerender but the map will not). Also, how I managed to verify which type of prop I should set for the leaflet API url... I did a silly switch case verification transforming the first char of the input value in a number and checking if its type would match. If it sounds confusing, you can check the code to make ir clearer. Anywho, I would love to get suggestions in which way I could go in order to check if the input value is an IP adress or an online domain.
tl;dr: you need to disable any ad blocker or anti-tracker in order to make the solution work :)
Community feedback
- @ikechukwu-peterPosted over 1 year ago
LeafletJs Map is immutable, therefore, even though the component rerenders the map does not, to overcome that you have to pass a component that will force the map to rerender too.
const ChangeMapView = ({ coords }: { coords: [number, number] }) => { const map = useMap(); map.setView(coords, map.getZoom()); return null; };
This forces the map to rerender using the new coords that you pass, my answer is written in TypeScript and useMaps is imported from react-leafletjs itself.
All you have to do is pass the <ChangeMapView /> component between the MapContainer with the same data that you pass to the map itself, once your data changes, it would reflect on the map.
<MapContainer> <ChangeView coords={[0.34, 1.23]} /> </MapContainer>
Here is a full working code sample.
import React, { FC } from "react"; import { MapContainer, TileLayer, Marker, Popup, useMap } from "react-leaflet"; import * as L from "leaflet"; import { IMAP } from "../@types/map"; import "leaflet/dist/leaflet.css"; export const Map: FC<IMAP> = ({ data }) => { //change map view since map container is immutable const ChangeMapView = ({ coords }: { coords: [number, number] }) => { const map = useMap(); map.setView(coords, map.getZoom()); return null; }; return ( <MapContainer center={[data?.latitude, data?.longitude]} zoom={13} scrollWheelZoom={false} style={{ width: "100vw", height: "100vh", zIndex: 8, }} > <TileLayer attribution='© <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors' url="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png" /> <Marker position={[data?.latitude, data?.longitude]} > <Popup>{data?.region}</Popup> </Marker> <ChangeMapView coords={[data?.latitude, data?.longitude]} /> </MapContainer> ); };
Marked as helpful1@LisandraFerrazPosted over 1 year ago@ikechukwu-peter For some reason, now if I don't use your/my update map function the map is rerendering 🤔 Well, in any case I will keep your suggestion on the final project, it totally makes sense, I had no idea about this trick.
Appreciate you!
0@ikechukwu-peterPosted over 1 year ago@LisandraFerraz I might not be able to say why it works without an updating function, however, having a function to update the map is the way to go since the MapContainer is immutable.
I am glad I could help.
1
Please log in to post a comment
Log in with GitHubJoin our Discord community
Join thousands of Frontend Mentor community members taking the challenges, sharing resources, helping each other, and chatting about all things front-end!
Join our Discord