diff --git a/examples/reuse-map/README.md b/examples/reuse-map/README.md
new file mode 100644
index 00000000..71a79268
--- /dev/null
+++ b/examples/reuse-map/README.md
@@ -0,0 +1,7 @@
+
+

+
+
+## Example: Reuse Map
+
+This example showcases how to reuse the same map without destroying it.
diff --git a/examples/reuse-map/app.css b/examples/reuse-map/app.css
new file mode 100644
index 00000000..22c2f75d
--- /dev/null
+++ b/examples/reuse-map/app.css
@@ -0,0 +1,30 @@
+body {
+ margin: 0;
+ font-family: Helvetica, Arial, sans-serif;
+}
+
+.control-panel {
+ position: absolute;
+ top: 0;
+ right: 0;
+ max-width: 320px;
+ background: #fff;
+ box-shadow: 0 2px 4px rgba(0,0,0,0.3);
+ padding: 12px 24px;
+ margin: 20px;
+ font-size: 13px;
+ line-height: 2;
+ color: #6b6b76;
+ text-transform: uppercase;
+ outline: none;
+}
+
+label {
+ display: inline-block;
+ width: 160px;
+}
+
+input {
+ margin-left: 20px;
+ max-width: 60px;
+}
diff --git a/examples/reuse-map/index.html b/examples/reuse-map/index.html
new file mode 100644
index 00000000..3e542913
--- /dev/null
+++ b/examples/reuse-map/index.html
@@ -0,0 +1,11 @@
+
+
+
+
+ react-map-gl Interaction Example
+
+
+
+
+
+
diff --git a/examples/reuse-map/package.json b/examples/reuse-map/package.json
new file mode 100644
index 00000000..8a52efc0
--- /dev/null
+++ b/examples/reuse-map/package.json
@@ -0,0 +1,20 @@
+{
+ "scripts": {
+ "start": "webpack-dev-server --progress --hot --open",
+ "start-local": "webpack-dev-server --env.local --progress --hot --open"
+ },
+ "dependencies": {
+ "react": "^16.0.0",
+ "react-dom": "^16.0.0",
+ "react-map-gl": "^3.2.0"
+ },
+ "devDependencies": {
+ "babel-core": "^6.21.0",
+ "babel-loader": "^6.2.10",
+ "babel-preset-es2015": "^6.18.0",
+ "babel-preset-react": "^6.16.0",
+ "babel-preset-stage-2": "^6.18.0",
+ "webpack": "^2.4.0",
+ "webpack-dev-server": "^2.4.0"
+ }
+}
diff --git a/examples/reuse-map/src/app.js b/examples/reuse-map/src/app.js
new file mode 100644
index 00000000..d920e4da
--- /dev/null
+++ b/examples/reuse-map/src/app.js
@@ -0,0 +1,27 @@
+import React, {Component} from 'react';
+import {render} from 'react-dom';
+import BartMap from './bart-map';
+
+export default class App extends Component {
+
+ state = {
+ showMap: true
+ };
+
+ _toggleMap() {
+ this.setState({showMap: !this.state.showMap});
+ }
+
+ render() {
+ const {showMap} = this.state;
+ return (
+
+
+ Toggle Map
+
+ {showMap &&
}
+
+ );
+ }
+
+}
diff --git a/examples/reuse-map/src/bart-map.js b/examples/reuse-map/src/bart-map.js
new file mode 100644
index 00000000..4ba9db4d
--- /dev/null
+++ b/examples/reuse-map/src/bart-map.js
@@ -0,0 +1,65 @@
+import React, {Component} from 'react';
+import MapGL, {Marker} from '../../../src';
+
+import bartStations from '../../data/bart-station.json';
+
+const MAPBOX_TOKEN = ''; // Set your mapbox token here
+
+import MARKER_STYLE from './marker-style';
+
+export default class BartMap extends Component {
+
+ state = {
+ viewport: {
+ latitude: 37.729,
+ longitude: -122.36,
+ zoom: 11,
+ bearing: 0,
+ pitch: 50,
+ width: 500,
+ height: 500
+ },
+ settings: {
+ dragPan: true,
+ dragRotate: true,
+ scrollZoom: true,
+ touchZoom: true,
+ touchRotate: true,
+ keyboard: true,
+ doubleClickZoom: true,
+ minZoom: 0,
+ maxZoom: 20,
+ minPitch: 0,
+ maxPitch: 85
+ }
+ };
+
+ _onViewportChange = viewport => this.setState({viewport});
+
+ _renderMarker(station, i) {
+ const {name, coordinates} = station;
+ return (
+
+ {name}
+
+ );
+ }
+
+ render() {
+ const {viewport, settings} = this.state;
+ return (
+
+
+ { bartStations.map(this._renderMarker) }
+
+ );
+ }
+
+}
diff --git a/examples/reuse-map/src/marker-style.js b/examples/reuse-map/src/marker-style.js
new file mode 100644
index 00000000..ab6546eb
--- /dev/null
+++ b/examples/reuse-map/src/marker-style.js
@@ -0,0 +1,30 @@
+export default `
+.station:before {
+ content: ' ';
+ display: inline-block;
+ width: 8px;
+ height: 8px;
+ background: red;
+ border-radius: 8px;
+ margin: 0 8px;
+}
+.station {
+ border-radius: 20px;
+ padding-right: 12px;
+ margin: -12px;
+ color: transparent;
+ line-height: 24px;
+ font-size: 13px;
+ white-space: nowrap;
+}
+.station span {
+ display: none;
+}
+.station:hover {
+ background: rgba(0,0,0,0.8);
+ color: #fff;
+}
+.station:hover span {
+ display: inline-block;
+}
+`;
diff --git a/examples/reuse-map/src/root.js b/examples/reuse-map/src/root.js
new file mode 100644
index 00000000..715cac95
--- /dev/null
+++ b/examples/reuse-map/src/root.js
@@ -0,0 +1,6 @@
+/* global document */
+import React from 'react';
+import ReactDOM from 'react-dom';
+import App from './app';
+
+ReactDOM.render(, document.body.appendChild(document.createElement('div')));
diff --git a/examples/reuse-map/webpack.config.js b/examples/reuse-map/webpack.config.js
new file mode 100644
index 00000000..1a53c5fd
--- /dev/null
+++ b/examples/reuse-map/webpack.config.js
@@ -0,0 +1,57 @@
+// NOTE: To use this example standalone (e.g. outside of deck.gl repo)
+// delete the local development overrides at the bottom of this file
+
+// avoid destructuring for older Node version support
+const resolve = require('path').resolve;
+const webpack = require('webpack');
+
+// Otherwise modules imported from outside this directory does not compile.
+// Also needed if modules from this directory were imported elsewhere
+// Seems to be a Babel bug
+// https://github.com/babel/babel-loader/issues/149#issuecomment-191991686
+const BABEL_CONFIG = {
+ presets: [
+ 'es2015',
+ 'react',
+ 'stage-2'
+ ].map(function configMap(name) {
+ return require.resolve(`babel-preset-${name}`);
+ })
+};
+
+const config = {
+ entry: {
+ app: resolve('./src/root.js')
+ },
+
+ devtool: 'source-map',
+
+ module: {
+ rules: [{
+ // Compile ES2015 using bable
+ test: /\.js$/,
+ include: [resolve('.')],
+ exclude: [/node_modules/],
+ use: [{
+ loader: 'babel-loader',
+ options: BABEL_CONFIG
+ }]
+ }]
+ },
+
+ resolve: {
+ alias: {
+ // From mapbox-gl-js README. Required for non-browserify bundlers (e.g. webpack):
+ 'mapbox-gl$': resolve('./node_modules/mapbox-gl/dist/mapbox-gl.js')
+ }
+ },
+
+ // Optional: Enables reading mapbox token from environment variable
+ plugins: [
+ new webpack.EnvironmentPlugin(['MapboxAccessToken'])
+ ]
+};
+
+// Enables bundling against src in this repo rather than the installed version
+module.exports = env => env && env.local ?
+ require('../webpack.config.local')(config)(env) : config;
diff --git a/src/mapbox/mapbox.js b/src/mapbox/mapbox.js
index c4537866..b31c7cc6 100644
--- a/src/mapbox/mapbox.js
+++ b/src/mapbox/mapbox.js
@@ -33,8 +33,7 @@ function noop() {}
const propTypes = {
// Creation parameters
- // container: PropTypes.DOMElement || String
-
+ container: PropTypes.object, /** The container to have the map. */
mapboxApiAccessToken: PropTypes.string, /** Mapbox API access token for Mapbox tiles/styles. */
attributionControl: PropTypes.bool, /** Show attribution control or not. */
preserveDrawingBuffer: PropTypes.bool, /** Useful when you want to export the canvas as a PNG. */
@@ -163,6 +162,17 @@ export default class Mapbox {
// Reuse a saved map, if available
if (props.reuseMaps && Mapbox.savedMap) {
this._map = this.map = Mapbox.savedMap;
+ // When reusing the saved map, we need to reparent the map(canvas) and other child nodes
+ // intoto the new container from the props.
+ // Step1: reparenting child nodes from old container to new container
+ const oldContainer = this._map.getContainer();
+ const newContainer = props.container;
+ newContainer.classList.add('mapboxgl-map');
+ while (oldContainer.childNodes.length > 0) {
+ newContainer.appendChild(oldContainer.childNodes[0]);
+ }
+ // Step2: replace the internal container with new container from the react component
+ this._map._container = newContainer;
Mapbox.savedMap = null;
// TODO - need to call onload again, need to track with Promise?
props.onLoad();