简体   繁体   English

React + leaflet + 路由机器:在 MapContainer 外部访问 map 时出现问题

[英]React + leaflet + routing machine : Problem accessing map outside MapContainer

I'm having trouble with my project, I want to draw a route and add markers on my map, but the event is triggered outside in a sidenav how collect the latitude and longitude of the marker.我的项目有问题,我想在我的 map 上绘制路线并添加标记,但事件是在 sidenav 外部触发的,如何收集标记的经纬度。 I can't call my map outside as I'm having the message:我无法在外面拨打我的 map,因为我收到以下消息:

useLeafletContext() can only be used in a descendant of useLeafletContext() 只能用于的后代

Architecture of the project: Apps项目架构:应用程序

  • App应用程序
    • SideBar侧边栏
    • Map Map
      • MapContainer地图容器
        • RoutingAdd(Where I need to create route) RoutingAdd(我需要创建路线的地方)

Routing.js路由.js

export default function RoutingAdd(props) {
const map = useMap();
//const dispatch = useDispatch();
const wayponts = useSelector((state) => state.startingPoints.value);
useEffect(() => {
    if (!map) return;
    console.log(wayponts);
    const routingControl = L.Routing.control({
        waypoints: [
            L.latLng(wayponts.start.lat, wayponts.start.long),
            L.latLng(wayponts.start.lat, wayponts.start.long)
        ],
        routeWhileDragging: true
    }).addTo(map);

    return () => map.removeControl(routingControl);
}, [map]);

return null;

} }

Map.js Map.js

function Map(props) {
const position = [48.856614, 2.3522219]
return (
    <MapContainer style={{ width: "100%", height: "100vh", zIndex: 0 }}  center={position} zoom={13} >
        <TileLayer
            attribution='&copy; <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors'
            url="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png"
        />
        <BornesCluster />
        <RoutingAdd addStart={props.handleNewStart} addEnd={props.handleNewEnd}></RoutingAdd>
    </MapContainer>
);

} export default Map; } 导出默认值 Map;

Sidebar.js边栏.js

function IntputNavigtion() {
    const dispatch = useDispatch();
    const map = useMap();
    function handleStartPoint(event) {
        console.log(event);
        //map.panTo(new LatLng(event.value[0], event.value[1], 0));
        dispatch(createStart({start:{lat: event.value[0], long: event.value[1]}}));
    }
    return (
        <div>
            <form>
                <select className="form-select" aria-label="Default select example">
                    <option selected>Choisir un modèle de voiture</option>
                    <option value="1">Telsa Model 3</option>
                    <option value="2">Zoe</option>
                </select>
                <hr />
                <InputAddresseGeocode
                    label="Point de départ"
                    placeholder="Entrer un point de départ"
                    valueSelectedCall={handleStartPoint}
                ></InputAddresseGeocode>
                <InputAddresseGeocode label="Point d'arrivé" placeholder="Entrer une addresse d'arrivé"></InputAddresseGeocode>
            </form>

            <button className="btn btn-primary mt-2">
                Calculer
            </button>
        </div>
    );
}

function SideBar() {

    const [toggled, setToggled] = useState('toggled');
    function toggleSideBar() {
        if(toggled == 'toggled') setToggled('hide')
        else setToggled('toggled')
    }

    function handleStartUpdate() {

    }

    function handleEndUpdate() {

    }

    return (
        <main>
            <button className={'btn btn-primary button-toggle button-toggle-' + toggled} onClick={toggleSideBar}><i className="fa fa-solid fa-bars"></i></button>
            <div id="wrapper" className={'d-flex flex-column flex-shrink-0 p-3 bg-light ' + toggled} style={{width: '360px', position: 'fixed', zIndex: '1',
                height: '100%', right: '0', top: '0'}}>
                <a href="/" className="d-flex align-items-center mb-3 mb-md-0 me-md-auto link-dark text-decoration-none">
                    <span className="fs-4">Navigation</span>
                </a>
                <hr />
                <IntputNavigtion />
            </div>
        </main>
    );
}

export default SideBar;

If anyone has an idea to communicate between these two components or to rethink about how to create the route, thank-you如果有人有想法在这两个组件之间进行通信或重新考虑如何创建路由,谢谢

The only way you can useMap() is inside the <MapContainer> .您可以使用useMap()的唯一方法是在<MapContainer>内部。 However you can pass a ref to the map from inside to the outside.但是,您可以从内部向外部传递对 map 的ref Since your components are really nested, you'll have to pass it from component to component, which isn't great, and you can avoid doing that by creating a new Context or using a global state manager like zustand or redux .由于您的组件确实是嵌套的,因此您必须将它从一个组件传递到另一个组件,这不是很好,并且您可以通过创建一个新的 Context 或使用全局 state 管理器(如zustandredux )来避免这样做。 However im gonna tell you the quick and dirty way to do this.但是,我会告诉您执行此操作的快速而肮脏的方法。

in App.js在 App.js 中

import { useRef } from "react"
function App(props) {
const mapRef = useRef();

return (
  <div>
   ...
   <Sidebar mapRef={mapRef}/>
   <Map mapRef={mapRef}/>
   ...
  </div>
)
}

in Map.js在 Map.js

...
<RoutingAdd mapRef={props.mapRef} addStart={props.handleNewStart} addEnd={props.handleNewEnd}/>
...

in Routing.js在 Routing.js 中

export default function RoutingAdd(props) {
const map = useMap();
props.mapRef.current = map;
...

in Sidebar.js在 Sidebar.js 中

function SideBar(props) {
  const map = props.mapRef.current
...

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM