Skip to content

Commit 3d3aa15

Browse files
committed
feat(Map): stateless map component
1 parent 22d9242 commit 3d3aa15

2 files changed

Lines changed: 64 additions & 39 deletions

File tree

src/Map.js

Lines changed: 55 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -1,47 +1,78 @@
11
"use strict";
2-
var React = require("react/addons");
2+
var React = require("react/addons"),
3+
deepEqual = require("deep-equal"),
34

4-
var ChildMixin = require("./mixins/ChildMixin");
5-
var EventBindingMixin = require("./mixins/EventBindingMixin");
5+
expose_getters_from = require("./helpers/expose_getters_from"),
6+
EventBindingMixin = require("./mixins/EventBindingMixin");
7+
8+
function ensure_map_created (component, createdCallback, createFactory) {
9+
var {context} = component,
10+
map = context.getMap(),
11+
noMap = !map;
12+
13+
if (noMap && context.getApi() && createFactory) {
14+
map = createFactory(component, context);
15+
}
16+
if (map) {
17+
createdCallback(map);
18+
if (noMap) {
19+
component.setState({_initialized: true});
20+
}
21+
}
22+
}
23+
24+
function create_map (component, context) {
25+
var {Map} = context.getApi(),
26+
map = new Map(
27+
component.refs.mapCanvas.getDOMNode(),
28+
component.props
29+
);
30+
expose_getters_from(component, Map.prototype, map);
31+
return context._set_map(map);
32+
}
633

734
module.exports = React.createClass({
835
displayName: "Map",
936

10-
mixins: [ChildMixin, EventBindingMixin],
37+
mixins: [EventBindingMixin],
1138

1239
contextTypes: {
40+
getMap: React.PropTypes.func,
41+
getApi: React.PropTypes.func,
42+
hasMap: React.PropTypes.func,
1343
_set_map: React.PropTypes.func
1444
},
1545

46+
getInitialState () {
47+
return {
48+
_initialized: false
49+
};
50+
},
51+
52+
shouldComponentUpdate(nextProps, nextState) {
53+
return !deepEqual(nextProps, this.props) || nextState._initialized !== this.state._initialized;
54+
},
55+
1656
componentDidMount () {
17-
var {context} = this;
18-
if (!context.getApi()) return;
19-
if (context.hasMap()) return;
20-
this.add_listeners(this._init_map());
57+
ensure_map_created(this, this.add_listeners, create_map);
2158
},
2259

2360
componentWillUpdate () {
24-
var {context} = this;
25-
if (!context.getApi()) return;
26-
if (context.hasMap()) return;
27-
this.clear_listeners(context.getMap());
61+
ensure_map_created(this, this.clear_listeners);
2862
},
2963

3064
componentDidUpdate () {
31-
var {context} = this;
32-
if (!context.getApi()) return;
33-
if (context.hasMap()) {
34-
this.context.getMap().setOptions(this.props);
35-
} else {
36-
this.add_listeners(this._init_map());
37-
}
65+
ensure_map_created(this, (map) => {
66+
map.setOptions(this.props);
67+
this.add_listeners(map);
68+
}, create_map);
3869
},
3970

4071
componentWillUnmount () {
41-
var {context} = this;
42-
if (!context.getApi()) return;
43-
if (context.hasMap()) return;
44-
this.clear_listeners(context.getMap());
72+
ensure_map_created(this, (map) => {
73+
this.clear_listeners(map);
74+
this.context._set_map(null);
75+
});
4576
},
4677

4778
render () {
@@ -52,22 +83,7 @@ module.exports = React.createClass({
5283
return "bounds_changed center_changed click dblclick drag dragend dragstart heading_changed idle maptypeid_changed mousemove mouseout mouseover projection_changed resize rightclick tilesloaded tilt_changed zoom_changed";
5384
},
5485

55-
_init_map () {
56-
var {context} = this;
57-
var {Map} = context.getApi();
58-
var map = new Map(
59-
this.refs.mapCanvas.getDOMNode(),
60-
this.props
61-
);
62-
this.expose_getters_from(Map.prototype, map);
63-
return context._set_map(map);
64-
},
65-
6686
_render (props, state) {
67-
return <div ref="mapCanvas"
68-
id={props.id}
69-
className={props.className}
70-
style={props.style}>
71-
</div>;
87+
return <div ref="mapCanvas" {...props}></div>;
7288
}
7389
});

src/helpers/expose_getters_from.js

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
"use strict";
2+
3+
module.exports = (component, prototype, instance) => {
4+
Object.keys(prototype).forEach((key) => {
5+
if (key.match(/^get/) && !key.match(/Map$/)) {
6+
component[key] = instance[key].bind(instance);
7+
}
8+
});
9+
};

0 commit comments

Comments
 (0)