简体   繁体   中英

React Render HTML to Infowindow using @React-Google-Maps/api

How do I to render html in google maps Infowindow?

I have tried several different ways to do it, but none of them seems to work.

My code:

import React, { Component, useState } from 'react';
import ReactDOMServer from 'react-dom/server';
import { GoogleMap, LoadScript, useLoadScript, InfoWindow, Marker, } from '@react-google-maps/api'

export class MarkerWithInfoWindow extends React.Component {

    constructor() {
        super();
        this.state = {
            isOpen: false
        }
        this.onToggleOpen = this.onToggleOpen.bind(this);
        this.onEventWindowClick = this.onEventWindowClick.bind(this)
    }

    onToggleOpen() {
        this.setState({
            isOpen: !this.state.isOpen
        });
    }



    render() {

        const imgUrl = this.props.icon;
        return (<Marker
            title={this.props.title}
            position={this.props.position}

            icon={{
                url: imgUrl,
            }}
        >
            {this.state.isOpen && <InfoWindow
                onCloseClick={this.onToggleOpen}
                position={this.props.position}
                onMouseOut={this.onToggleOpen}
                pixelOffset={{ width: 25, height: 25 }}
                zIndex={-1}
                onClick={this.onEventWindowClick(this)} 
            >
                <> {ReactDOMServer.renderToString(this.props.content)}</>
            </InfoWindow>}
        </Marker>)
    }
}

my result looks like this:

在此处输入图像描述

I guess content prop is passed as HTML string, then dangerouslySetInnerHTML needs to be set to render it as html instead of returning it as a plain string, for instance:

const InfoWindowContent = () => <div dangerouslySetInnerHTML={{ __html: this.props.content }}></div>;

Usage

<InfoWindow
     onCloseClick={this.onToggleOpen}
     position={this.props.position}>
      <InfoWindowContent/>
</InfoWindow>

Demo

I've done this only as a functional component. According to the Google Map API docs, the desired HTML content can be passed as the value of the content property of the InfoWindow instance at its instantiation. According to the documentation of the react-google-maps/api , the (initial) options can be passed as a prop in the InfoWindow JSX.

In my case, I recompute the InfoWindow content on the fly, so I keep that string as a piece of state ( dataWindowContent in my case). React guarantees that the InfoWindow component will be rerendered each time the state changes, so that's how I keep mine current.

Finally, the InfoWindow component is created with the InfoWindow component open by default. I keep mine closed until it has something to show, so I put that behavior in the onInfoWindowLoad handler.

You'll need a ref to the underlying Google Maps API instance -- the InfoWindow component conveniently passes that object as an argument when it invokes the onLoad handler. So here's a sketch of how you might do what you're attempting (note that I haven't exercised this, I'm just trying to say what you might try):

const MarkerWithInfoWindow = ( {content, title, position, icon, ...props} ) => {
  const [infoWindowContent, setInfoWindowContent] = useState(content);
  const [localPosition, setLocalPosition] = useState(position);
  const rawInfoWindowRef = useRef(null);

  const onInfoWindowLoad = (aRawInfoWindow) => {
    rawInfoWindowRef.current = aRawInfoWindow;
    if (''===infoWindowContent) {
      aRawInfoWindow.close();
    }
  };
  return (
    <GoogleMap>
      <Marker
        title={title}
        position={localPosition}
        icon={{url: icon}}
      >
      <InfoWindow
        onLoad={onInfoWindowLoad}
        onCloseClick={onInfoWindowClick}
        options={{content: infoWindowContent}}
        position={localPosition}         
      />
      </Marker>
    <GoogleMap>
  );
};

Note that I've passed your desired HTML into the InfoWindow instance as the value of its content parameter inside its option prop.

Note also that position and content props are used to initialize the corresponding local state. Use their setters to move the marker/infoWindow or move the map. Also note I've surrounded your Marker and InfoWindow with a containing GoogleMap. I'm pretty sure the components require this container. You might need set the center property of the containing map as another piece of state so that it changes if the position changes.

This approach lets you avoid the use of dangerouslySetInnerHTML . The only way to change infoWindowContent is to use its setter ( setInfoWindowContent ) and this will force a rerender of the component tree. In that re-render, the low-level InfoWindow instance will be updated with its new content automatically, and it will render the HTML.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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