I'm working on a map-based app that uses Google Map API to create markers and its info window in React.js. The infowindow.setContent()
only accepts either a String
or HTML
. It's impossible for me to pass in String
as I have a button
that links to a specific method in another react component (something like: _this.props.addList(place)
). Thus I must fill the argument as HTML DOM as the following lines of code:
var div = document.createElement('div');
var title = document.createElement('h4');
title.innerHTML = place.name;
var btn = document.createElement('button');
btn.className = 'btn btn-danger btn-block';
btn.appendChild(document.createTextNode('I want to go here !!'));
div.appendChild(title).appendChild(btn);
google.maps.event.addListener(marker, 'click', function() {
infowindow.setContent( div );
infowindow.open(map, this);
});
btn.addEventListener('click', function() {
_this.props.addList(place);
});
The codes work for me but I don't wanna create elements one by one. I've also tried to pass the argument with a React component but it seems not working:
createMarker: function() {
/** Some other lines of code */
var _this = this;
google.maps.event.addListener(marker, 'click', function() {
infowindow.setContent( _this._renderInfoWindow(place) );
infowindow.open(map, _this);
});
},
// my infowindow rendering method
_renderInfoWindow: function(place) {
return(
<div>
<h4>{place.name}</h4>
<p>{place.cost}</p>
<button className="btn btn-danger btn-block" onClick={this.props.addList.bind(this, place)}>I want to go here !! </button>
</div>
)
},
so is there another way to at least convert a react component to HTML so that I don't have to write document.createElement()
one by one?
Thanks
Simply adding React components into HTML code is not possible, because <MyComponent></MyComponent> is not HTML at all, it is JSX.
React implements a browser-independent DOM system for performance and cross-browser compatibility. We took the opportunity to clean up a few rough edges in browser DOM implementations. In React, all DOM properties and attributes (including event handlers) should be camelCased.
To get HTML from a react component, you can use the ReactDOMServer. renderToString method (doc) used mainly for SSR purpose.
When the state of a component changes, React updates the virtual DOM tree. Once the virtual DOM has been updated, React then compares the current version of the virtual DOM with the previous version of the virtual DOM. This process is called “diffing”.
You can render a ReactElement in a detached DOM Node via React.render
. Thus, the following code should work for you.
createMarker: function() {
/** Some other lines of code */
_this = this;
google.maps.event.addListener(marker, 'click', function() {
var div = document.createElement('div');
ReactDOM.render( _this._renderInfoWindow(place), div );
infowindow.setContent( div );
infowindow.open(map, this);
});
},
You could also use React's renderToString() method
_renderInfoWindow: function(place) {
return React.renderToString(
<div>
<h4>{place.name}</h4>
<p>{place.cost}</p>
<button className="btn btn-danger btn-block" onClick={this.props.addList.bind(this, place)}>I want to go here !! </button>
</div>
);
}
This should work for a simple component as shown. React.renderToString() will return only the html for the component.
For newer versions of React
import ReactDOMServer from "react-dom/server";
let html = ReactDOMServer.renderToString(<div>...</div>)
This should render the HTML.
import ReactDOMServer from "react-dom/server";
const html = ReactDOMServer.renderToString(<div>...</div>)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With