如何在任何 child 上使用相同的 google 地图组件实例?

How to use the same google map component instance on any child?

我正在寻找一种在我的应用程序中的任何位置使用相同 google 地图实例的方法。毕竟每个地图加载都是收费的...

我正在使用 google-map-react. A new Map 实例是在 ComponentDidMount 上创建的,所以对我来说,第一个要求是保持该组件已安装,很可能靠近组件树的顶部。

最终结果应该是任何想要渲染地图的组件都应该:

如有任何帮助,我们将不胜感激。

您可以尝试使用 Portals

来实现

Portals 提供了第一种class 方法来将子项渲染到 DOM 节点中,该节点存在于父组件的 DOM 层次结构之外。

但是,用户对地图所做的每项更改(缩放、图层等)都将保留,因此当您在另一个部分渲染地图时,您也可以将地图重置为初始状态。

门户确实是正确的方向。我想出了以下方法:

  1. 添加兄弟节点到index.html:
<!-- Root node of React app -->
<div id="root"></div>

<!-- Keep the map here while not in use -->
<div id="map-bench">
  <!-- Create the portal using this node as container (2nd argument) -->
  <div id="map-container" style="height: 100%; width: 100%"></div>
</div>
  1. 制作一个在门户内呈现地图的组件,然后将其安装在树顶部附近的某个位置;重点是防止地图卸载。
return createPortal(renderMap(), document.getElementById("map-container"));
  1. 使用回调引用将地图插入到您需要的任何地方。如何在您的组件上实际使用它取决于您;我做了一个钩子returns这个函数。
    const registerMapOutlet = (rootNode: HTMLDivElement | null) => {
      // THE MAP
      const mapNode = document.getElementById("map-container");

      // Bail out if map node is not found
      if (mapNode === null) return;

      // on mount: Attach map
      if (rootNode) {
        rootNode.replaceWith(mapNode);

        console.log("REGISTERED MAP OUTLET");

        // GoogleMapReact won't load/mount until it is first used
        dispatch(mountMapIfNeeded());
      }

      // on unmount: Return map to bench node
      else {
        const mapBenchNode = document.getElementById("map-bench");

        if (mapBenchNode === null) {
          console.warn("Map Bench node was not found");
          return;
        }

        mapBenchNode.appendChild(mapNode);
      }
    }
  1. 最后,像这样在任何组件上使用地图:
// You can pass GoogleMapReact props to this hook
const { registerMapOutlet } = useMapOutlet({});

return <div ref={registerMapOutlet}></div>

google-map-react 的 1.1.5 版本引入了一个 shouldUnregisterMapOnUnmount 道具。我会尽快试验并更新我的答案。