I'm trying to figure out how to work with mapping APIs like openlayers, leaflet, mapbox, google maps, etc. and React + Redux.
My goal is to make the map object available to all other components of the app, without defining it as a global variable.
In React without Redux, I would construct the openlayers map object in the top-level component of the application, save it to state, and then pass down to children components as props. That has worked okay for me, but I'm trying to learn how to fit Redux into the application.
So consider this use case: I have an application with two main components: a map and a menu, both residing within the master App component. The menu has one tool that will enable a user to add a geojson file to the map. I want to construct the openlayers map object in the Map component, but the AddFile tool needs to know the map object in order to work.
Here's the relevant portion of the map component:
componentDidMount() {
// define ol modules after React component mounts (for SSR)
const Map = require('ol/map').default;
const View = require('ol/view').default;
const TileLayer = require('ol/layer/tile').default;
const OSM = require('ol/source/osm').default;
const olMap = new Map({
target: 'map',
layers: [
new TileLayer({
source: new OSM(),
}),
],
view: new View({
center: [0, 0],
zoom: 3,
}),
});
this.loadMap(olMap);
}
loadMap = olMap => {
this.props.dispatch(loadMap(olMap));
}
render() {
return (
<div id="map">
</div>
);
}
Which dispatches the loadMap action:
export function loadMap(olMap) {
return {
type: 'LOAD_MAP',
olMap,
};
}
And is handled by the reducer:
export default function mapReducer(state, action) {
if (action.type === 'LOAD_MAP') {
return state.merge({
olMap: action.olMap,
});
}
}
This is the same pattern I've used to get simpler items into the redux store, but when I run this I'm getting errors about Maximum call stack size exceeded.
I'm guessing that this issue is coming from one of two things:
- The ol map object is mutable
- The ol map object has circular references
Any ideas on how I can avoid this error, or should I stick with the standard React approach that was working for me and keep the map object away from Redux?
state.set
instead ofstate.merge
does that work? Or store it outside of an Immutable object?