Skip to content

Commit 14d9273

Browse files
committed
feat(async/withScriptjs): provide HOC for loading googleMapURL with scriptjs
* `withScriptjs` requires a prop: `googleMapURL` * `withScriptjs` requires a prop: `loadingElement` BREAKING CHANGE: Apply `withScriptjs` HOC before `withGoogleMaps` HOC. Before: ```js <ScriptjsLoader hostname={"maps.googleapis.com"} pathname={"/maps/api/js"} query={{v: `3.${ AsyncGettingStarted.version }`, libraries: "geometry,drawing,places"}} loadingElement={ <div {...this.props} style={{ height: "100%" }}> <FaSpinner /> </div> } containerElement={ <div {...this.props} style={{ height: "100%" }} /> } googleMapElement={ <GoogleMap ref={googleMap => { googleMap && console.log(`Zoom: ${ googleMap.getZoom() }`); }} defaultZoom={3} defaultCenter={{lat: -25.363882, lng: 131.044922}} onClick={::this.handleMapClick} > <Marker {...this.state.marker} onRightclick={this.handleMarkerRightclick} /> </GoogleMap> } /> ``` After: ```js // Wrap all `react-google-maps` components with `withGoogleMap` HOC // then wraps it into `withScriptjs` HOC // It loads Google Maps JavaScript API v3 for you asynchronously. // Name the component AsyncGettingStartedExampleGoogleMap const AsyncGettingStartedExampleGoogleMap = withScriptjs( withGoogleMap( props => ( <GoogleMap ref={props.onMapLoad} defaultZoom={3} defaultCenter={{ lat: -25.363882, lng: 131.044922 }} onClick={props.onMapClick} > {props.markers.map(marker => ( <Marker {...marker} onRightClick={() => props.onMarkerRightClick(marker)} /> ))} </GoogleMap> ) ); // Then, render it: render( <GettingStartedGoogleMap googleMapURL="https://maps.googleapis.com/maps/api/js?v=3.exp" loadingElement={ <div style={{ height: `100%` }}> <FaSpinner style={{ display: `block`, width: `80px`, height: `80px`, margin: `150px auto`, animation: `fa-spin 2s infinite linear`, }} /> </div> } containerElement={ <div style={{ height: `100%` }} /> } mapElement={ <div style={{ height: `100%` }} /> } onMapLoad={_.noop} onMapClick={_.noop} markers={markers} onMarkerRightClick={_.noop} />, document.getElementById('root') ); ```
1 parent f61724c commit 14d9273

File tree

4 files changed

+98
-220
lines changed

4 files changed

+98
-220
lines changed

src/lib/async/ScriptjsGoogleMap.js

Lines changed: 0 additions & 56 deletions
This file was deleted.

src/lib/async/ScriptjsLoader.js

Lines changed: 0 additions & 130 deletions
This file was deleted.

src/lib/async/withScriptjs.js

Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
import _ from "lodash";
2+
3+
import invariant from "invariant";
4+
5+
import canUseDOM from "can-use-dom";
6+
7+
import getDisplayName from "react-display-name";
8+
9+
import {
10+
default as React,
11+
PropTypes,
12+
Component,
13+
} from "react";
14+
15+
const LOAIDNG_STATE_NONE = `NONE`;
16+
const LOAIDNG_STATE_BEGIN = `BEGIN`;
17+
const LOAIDNG_STATE_LOADED = `LOADED`;
18+
19+
export default function withScriptjs(WrappedComponent) {
20+
return class Container extends Component {
21+
static displayName = `withScriptjs(${getDisplayName(WrappedComponent)})`;
22+
23+
static propTypes = {
24+
loadingElement: PropTypes.node.isRequired,
25+
googleMapURL: PropTypes.string.isRequired,
26+
};
27+
28+
state = {
29+
loadingState: LOAIDNG_STATE_NONE,
30+
};
31+
32+
isUnmounted = false;
33+
34+
handleLoaded = this.handleLoaded.bind(this);
35+
36+
handleLoaded() {
37+
if (this.isUnmounted) {
38+
return;
39+
}
40+
this.setState({
41+
loadingState: LOAIDNG_STATE_LOADED,
42+
});
43+
}
44+
45+
componentWillMount() {
46+
const {
47+
loadingElement,
48+
googleMapURL,
49+
} = this.props;
50+
invariant(!!loadingElement && !!googleMapURL,
51+
`Required props loadingElement or googleMapURL is missing. You need to provide both of them.`
52+
);
53+
}
54+
55+
componentDidMount() {
56+
const {
57+
loadingState,
58+
} = this.state;
59+
if (loadingState !== LOAIDNG_STATE_NONE || !canUseDOM) {
60+
return;
61+
}
62+
this.setState({
63+
loadingState: LOAIDNG_STATE_BEGIN,
64+
});
65+
// Don't load scriptjs as dependency since we want this module be used on server side.
66+
// eslint-disable-next-line global-require
67+
const scriptjs = require(`scriptjs`);
68+
const {
69+
googleMapURL,
70+
} = this.props;
71+
scriptjs(googleMapURL, this.handleLoaded);
72+
}
73+
74+
componentWillUnmount() {
75+
this.isUnmounted = true;
76+
}
77+
78+
render() {
79+
const {
80+
loadingElement,
81+
googleMapURL, // eslint-disable-line no-unused-vars
82+
...restProps,
83+
} = this.props;
84+
85+
const {
86+
loadingState,
87+
} = this.state;
88+
89+
if (loadingState === LOAIDNG_STATE_LOADED) {
90+
return (
91+
<WrappedComponent {...restProps} />
92+
);
93+
} else {
94+
return loadingElement;
95+
}
96+
}
97+
};
98+
}

src/lib/utils/makeUrl.js

Lines changed: 0 additions & 34 deletions
This file was deleted.

0 commit comments

Comments
 (0)