I am trying to express my Openlayers application as a components based application. Having a single <Map /> component with childrens like <Marker />, I need to access my <Map /> component's this.map property from the <Marker />.
Take this markup from a representational component:
<Map center={[-1.81185, 52.44314]} zoom={6}>
<Marker title="This is a marker" coordinate={[-1.81185, 52.44314]} />
</Map>
The <Map /> component:
export default class Map extends React.Component {
static propTypes = {
center: React.PropTypes.array.isRequired,
zoom: React.PropTypes.number.isRequired
}
constructor(props) {
super(props);
this.map = null;
}
componentDidMount() {
this.map = new ol.Map(/* code removed for brevity */);
}
renderChildren() {
const { children } = this.props;
if (!children) return;
return React.Children.map(children, c => {
return React.cloneElement(c, {
map: this.map
});
})
}
render() {
return <div id="map">{this.renderChildren()}</div>
}
}
The <Marker /> component:
export default class Marker extends React.Component {
static propTypes = {
map: React.PropTypes.object,
coordinate: React.PropTypes.array.isRequired,
title: React.PropTypes.string
}
componentDidMount() {
const { map, coordinate, title } = this.props;
if (!map) return;
var marker = createMarkerAndPlaceOn(map);
}
render() {
return null;
}
}
As you can see I tried passing the this.map property down, by cloning the element and give it the property.
However, because I need to rely on the DOM node #map to be rendered, I can first initialize my new ol.Map() in the <Map />'s componentDidMount() method. This means my child component does not get the instance of this.map when rendering.
Is there any clean, non anti-pattern, way of achieving this?