Выпадающий список не изменяет состояние, если он является дочерним элементом карты листовки

#reactjs #react-select #react-leaflet

Вопрос:

Я создал демонстрацию проблемы здесь; кто-нибудь знает, почему выбор из вариантов не изменяет состояние? В основном выглядит так:

 <MapContainer>
        <Control position="topleft" >
          <div style={{ width: "300px" }}>
            <Select
              value={sel}
              options={[
                { label: "a", value: 1 },
                { label: "b", value: 2 }
              ]}
              onChange={(sel) => this.setState({ sel })}
            />
          </div>
        </Control>
        <Control position="topright">
          <>
            <h3>Selection:</h3>
            {`${sel.label}:${sel.value}`}
          </>
        </Control>
</MapContainer
 

Ответ №1:

В итоге мне пришлось отсоединить и повторно прикрепить собственные обработчики событий DOM mousedown, которые были добавлены в контейнер карты с помощью react-листовки:

 const Control = ({ position, children, mapRef }) => {

    ...
    
    const restoreMapClick = () => {
        if(mapRef amp;amp; '_leaflet_events' in mapRef amp;amp; focus) {
            setFocus(false);
            mapHandlers.map(([id,fn]) => {
                mapRef.addEventListener('mousedown', fn, false);
                mapRef['_leaflet_events'][id] = fn;
            })
        }
    };
    const disableMapClick = () => {
        if(mapRef amp;amp; '_leaflet_events' in mapRef amp;amp; !focus) {
            const handlers = Object.entries(mapRef['_leaflet_events']).filter(([id,fn]) => id.startsWith('mousedown'));
            setMapHandlers(handlers);
            setFocus(true);
            handlers.map(([id,fn]) => {
                mapRef.removeEventListener('mousedown', fn, false);
                mapRef['_leaflet_events'][id] = null;
                }
            );
        }
    };

    return (
        <div className={positionClass}>
            <div className="leaflet-control leaflet-bar">
            {React.cloneElement(children, {restoreMapClick, disableMapClick})}
            </div>
        </div>
    )
}
 
 <MapContainer>
   ...
  whenCreated={ mapInstance => { this.setState({mapRef: mapInstance._container})} }
>
  {this.state.mapRef amp;amp; <Control position="topleft" mapRef={this.state.mapRef}>
      <YourActualComponentInTheControl/>
  </Control>}
</MapContainer>
 
 const YourActualComponentInTheControl = ({ disableMapClick, restoreMapClick }) => {

  ...

  return(
    <Select
      onChange={e=>{disableMapClick();/*useTypedValue*/}}
      onSelect={e=>{/*useClickedValue*/;restoreMapClick();}}
    />
  );
}