| 1 |
/* global google */ |
| 2 |
import _ from "lodash" |
| 3 |
import warning from "warning" |
| 4 |
import invariant from "invariant" |
| 5 |
import { getDisplayName } from "recompose" |
| 6 |
import PropTypes from "prop-types" |
| 7 |
import React from "react" |
| 8 |
import { MAP } from "./constants" |
| 9 |
export function withGoogleMap(BaseComponent) { |
| 10 |
const factory = React.createFactory(BaseComponent) |
| 11 |
class Container extends React.PureComponent { |
| 12 |
static displayName = `withGoogleMap(${getDisplayName(BaseComponent)})` |
| 13 |
static propTypes = { |
| 14 |
containerElement: PropTypes.node.isRequired, |
| 15 |
mapElement: PropTypes.node.isRequired, |
| 16 |
} |
| 17 |
static childContextTypes = { |
| 18 |
[MAP]: PropTypes.object, |
| 19 |
} |
| 20 |
state = { |
| 21 |
map: null, |
| 22 |
} |
| 23 |
handleComponentMount = _.bind(this.handleComponentMount, this) |
| 24 |
getChildContext() { |
| 25 |
return { |
| 26 |
[MAP]: this.state.map, |
| 27 |
} |
| 28 |
} |
| 29 |
componentWillMount() { |
| 30 |
const { containerElement, mapElement } = this.props |
| 31 |
invariant( |
| 32 |
!!containerElement && !!mapElement, |
| 33 |
`Required props containerElement or mapElement is missing. You need to provide both of them. |
| 34 |
The \`google.maps.Map\` instance will be initialized on mapElement and it's wrapped by\ |
| 35 |
containerElement. You need to provide both of them since Google Map requires the DOM to\ |
| 36 |
have height when initialized.` |
| 37 |
) |
| 38 |
} |
| 39 |
handleComponentMount(node) { |
| 40 |
if (this.state.map || node === null) { |
| 41 |
return |
| 42 |
} |
| 43 |
warning( |
| 44 |
`undefined` !== typeof google, |
| 45 |
`Make sure you've put a <script> tag in your <head> element to load Google Maps JavaScript API v3. |
| 46 |
If you're looking for built-in support to load it for you, use the "async/ScriptjsLoader" instead. |
| 47 |
See https://github.com/tomchentw/react-google-maps/pull/168` |
| 48 |
) |
| 49 |
// https://developers.google.com/maps/documentation/javascript/3.exp/reference#Map |
| 50 |
const map = new google.maps.Map(node) |
| 51 |
this.setState({ map }) |
| 52 |
} |
| 53 |
render() { |
| 54 |
const { containerElement, mapElement, ...restProps } = this.props |
| 55 |
const { map } = this.state |
| 56 |
if (map) { |
| 57 |
return React.cloneElement( |
| 58 |
containerElement, |
| 59 |
{}, |
| 60 |
React.cloneElement(mapElement, { |
| 61 |
ref: this.handleComponentMount, |
| 62 |
}), |
| 63 |
<div>{factory(restProps)}</div> |
| 64 |
) |
| 65 |
} else { |
| 66 |
return React.cloneElement( |
| 67 |
containerElement, |
| 68 |
{}, |
| 69 |
React.cloneElement(mapElement, { |
| 70 |
ref: this.handleComponentMount, |
| 71 |
}), |
| 72 |
<div /> |
| 73 |
) |
| 74 |
} |
| 75 |
} |
| 76 |
} |
| 77 |
return Container |
| 78 |
} |
| 79 |
export default withGoogleMap |
Комментарии