My code is here:
import React, { useState, useEffect, useRef } from 'react'; import restaurantsInfo from "./RestaurantsList.json"; import "./App.css"; import { MapContainer, Marker, Popup, TileLayer, useMapEvents } from "react-leaflet"; import { Icon, latLng } from "leaflet"; import Restaurants from "./Restaurants.js"; import LocationMarker from "./LocationMarker.js"; import L from 'leaflet'; export default function App() { function LocationMarker() { const [position, setPosition] = useState(null); const [bbox, setBbox] = useState([]); const map = useMap(); useEffect(() => { map.locate().on("locationfound", function (e) { setPosition(e.latlng); map.flyTo(e.latlng, map.getZoom()); const radius = e.accuracy; const circle = L.circle(e.latlng, radius); circle.addTo(map); setBbox(e.bounds.toBBoxString().split(",")); }); }, [map]); return position === null ? null : ( <Marker position={position} icon={icon}> <Popup> You are here. <br /> Map bbox: <br /> <b>Southwest lng</b>: {bbox[0]} <br /> <b>Southwest lat</b>: {bbox[1]} <br /> <b>Northeast lng</b>: {bbox[2]} <br /> <b>Northeast lat</b>: {bbox[3]} </Popup> </Marker> ); } return ( <div class="container"> <div style={{height: '400px', width: '500px'}} class="map"> <MapContainer center={[49.1951, 16.6068]} zoom={defaultZoom} scrollWheelZoom={false}> <TileLayer attribution='© <a href="http://osm.org/copyright">OpenStreetMap</a> contributors' url="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png" /> <MapContainer/>
My question is, how can I use bbox to check if some of my markers is inside the map? When I try to apply:
if (bbox.contains(marker.getPosition())===true)
or this:
if ((bbox[1] < marker.lat< bbox[3])&& (bbox[2] <marker.long <bbox[4]))
I faced the error: bbox is not defined
I don’t know how to return bbox from function LocationMarker(). I would be grateful for any help. Thank you.
Advertisement
Answer
You need to follow a slight different approach then:
Declare bbox
variable on the parent component(App
) and store the instance. You will need it to be able to use contains method later. you can pass bbox
and setBbox
as props on LocationMarker comp. Doing that you will have the communication between the two components.
Also move the LocationMarker
comp outside the App.
Here is the LcoationMarker
component:
function LocationMarker({ bbox, setBbox }) { const [position, setPosition] = useState(null); const map = useMap(); useEffect(() => { map.locate().on("locationfound", function (e) { setPosition(e.latlng); map.flyTo(e.latlng, map.getZoom()); const radius = e.accuracy; const circle = L.circle(e.latlng, radius); circle.addTo(map); setBbox(e.bounds); }); }, [map,setBbox]); const boundingBox = bbox ? bbox.toBBoxString().split(",") : null; if (!position || !bbox) return null; return ( <Marker position={position} icon={icon}> <Popup> You are here. <br /> Map bbox: <br /> <b>Southwest lng</b>: {boundingBox[0]} <br /> <b>Southwest lat</b>: {boundingBox[1]} <br /> <b>Northeast lng</b>: {boundingBox[2]} <br /> <b>Northeast lat</b>: {boundingBox[3]} </Popup> </Marker> ); }
Here is the App component. You can use bbox isntance in this example via a button. Make sure to check that bbox is defined before using it.
function App() { const [bbox, setBbox] = useState(null); const handleClick = () => { if (bbox) alert(bbox.contains([49.1951, 16.6068])); }; return ( <> <MapContainer ...> ... <LocationMarker bbox={bbox} setBbox={setBbox} /> </MapContainer> <button onClick={handleClick}>bbox contains</button> </> ); }
Here is a demo with all the pieces together