使用 geojson pointToLayer 函数时需要正确的方法在 Leaflet 弹出窗口中渲染 jsx 组件

Nen*_*nad 4 leaflet react-leaflet

您好,有什么方法可以将 jsx 组件传递给 bindPopup 函数,以便我可以在单击按钮时推送 redux 命令吗?

 pointToLayer={(
      geoJsonPoint: Feature<Point, DeviceProperties>,
      latlng,
    ) => {
      const marker = L.marker(latlng);
      marker.setIcon(
        markerIcon({ variant: geoJsonPoint.properties.relation }),
      );

      const sddds = (
        <div className="font-quicksand">
          <h2>{geoJsonPoint.properties.id}</h2>
          <h2>{geoJsonPoint.properties.name}</h2>
          <p>{geoJsonPoint.properties.description}</p>
          <p>{geoJsonPoint.properties.ownerId}</p>
          <a
            onClick={() => {
              dispatch(setDevice(geoJsonPoint.properties));
            }}
          >
            Open device details
          </a>
        </div>
      );

      marker.bindPopup(renderToString(sddds));
      return marker;
    }}
Run Code Online (Sandbox Code Playgroud)

我知道我可以使用反应传单组件,但这样我就无法将道具传递到每个标记选项中(我的意思是标记作为层)。

Nen*_*nad 5

这是我想到的两个解决方案,如果有人遇到同样的问题,我想与大家分享。

我使用 leaflet-react Popup组件的问题是,当我只映射 geojson 对象时,它不会将 geojson 属性传递给标记层,因为 React-leaflet Marker没有像 geojson 层那样的 api,我需要通过访问这些属性地图其他部分的标记图层。

解决方案一:

在 pointToLayer 方法中使用 ReactDOM.render(),react 将显示有关纯函数的警告,但它会起作用。你只是不应该渲染导入的组件,因为它会抱怨 store 和 redux 提供者,而是将组件代码粘贴到渲染中。如果您想避免警告,请创建另一个函数/挂钩并将其 useEffect() 内的代码渲染到容器(div 或其他内容)。

这是示例:

const popup = L.popup();
const marker = L.marker(latlng);
const container = L.DomUtil.create('div');
render(
  <div>
    <h2>{props.id}</h2>
    <h2>{props.name}</h2>
    <p>{props.description}</p>
    <p>{props.ownerId}</p>
    <a onClick={() => dispatch(setDevice(geoJsonPoint.properties))}></a>
  </div>,
  container,
);
popup.setContent(container);
marker.bindPopup(popup);
return marker;
Run Code Online (Sandbox Code Playgroud)

使用自定义钩子/函数:

const useRenderPopup = (props) => {
const container = L.DomUtil('div');
const dispatch = useAppDispatch()
useEffect(() => {
render(
  <div>
    <h2>{props.id}</h2>
    <h2>{props.name}</h2>
    <p>{props.description}</p>
    <p>{props.ownerId}</p>
    <a onClick={() => dispatch(setDevice(props.geoJsonPoint.properties))}></a>
  </div>,
  container,
);
},[])
return container;
}
Run Code Online (Sandbox Code Playgroud)

只需像 popup.setContent(useRenderPopup(someprop)) 这样调用这个函数,这样就不会出现警告。

解决方案2:

使用 renderToString() 和其他需要触发 redux update 附加事件侦听器的东西将所有内容渲染为静态。

const popup = L.popup();
const marker = L.marker(latlng);
const link = L.DomUtil.create('a');
const container = L.DomUtil.create('div');
const content = <DeviceSummary {...geoJsonPoint.properties} />;

marker.setIcon(markerIcon({ variant: geoJsonPoint.properties.relation }));

link.addEventListener('click', () =>
  dispatch(setDevice(geoJsonPoint.properties)),
);

link.innerHTML = 'Show device details';
container.innerHTML = renderToString(content);
container.appendChild(link);

popup.setContent(container);
marker.bindPopup(popup);
return marker;
Run Code Online (Sandbox Code Playgroud)

这里的 DeviceSummary 组件是静态的,因此我将其渲染为字符串,然后附加链接,并将 redux 回调添加为事件侦听器。

(除了自定义函数示例之外,这两种解决方案都进入 geoJSON 层内的 pointToLatyer 方法)