2

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:

  1. The ol map object is mutable
  2. 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?

5
  • Are you using any other React lifecycle method? Commented Oct 18, 2017 at 17:08
  • No. At one point I had shouldComponentUpdate() returning false, but I was just trying to see if I could make anything work. No other lifecycle methods in the map component.
    – bramb84
    Commented Oct 18, 2017 at 17:43
  • If you use state.set instead of state.merge does that work? Or store it outside of an Immutable object?
    – tcoopman
    Commented Oct 19, 2017 at 6:29
  • state.set instead of state.merge stopped the errors. The store isn't populating correctly, but that might be an issue somewhere else. I'll explore some more. Thanks!
    – bramb84
    Commented Oct 19, 2017 at 18:08
  • Could you please add an answer if you found a solution to your issue?
    – Alex
    Commented Jan 30, 2018 at 10:51

0