Reputation: 31
I'm using React and Redux to build my app. Now I want to embed a Mapbox GL map in one of the components, and create some states in my Redux to reflect the status of the map.
What is the best way to combine my React Redux app with Mapbox GL, so that my React elements can interact with the map?
Upvotes: 3
Views: 1472
Reputation: 2391
I'd start by considering the different responsibilities of React and Redux (because they are very different tools).
React is built to help render components on the web. You can build really awesome, complicated pieces of UI with it.
However, most mapping libraries (Mapbox, Leaflet) are inherently really complex. They handle their own rendering cycles pretty well.
The prevailing practice right now is to wrap the mapping library in a react component, so that you can use it within the react hierarchy of your project, but to delegate rendering within the map to the mapping library.
The wrapper can be something as simple as something that renders <div ref="mbMap" />
, and you'll be able to use your map library's functions on the map reference itself, and can control react component updates through the lifecylce methods like shouldComponentUpdate
.
It's usually a safe bet to think state === data
and most of the complexity in a component is data (think the image tiles in a map for instance). However, for the theory of redux to work, state needs to be represented as plain objects and serializable, which most map libraries are not.
There's some decent former research on just the redux piece of your question (see this conversation).
The general rule of thump is keep the data you need, to return the map to its current state, in the redux state tree. Examples would be zoom level, layers, locations, etc, but not the map / vector / svg data itself.
That way you can dispatch actions, which represent the change in your apps data you want to make, which in turn call the native rendering of the map library.
Think:
state = {
mapZoom: { boundaries: [lat, lng], zoomLevel: 5},
pokeStops: {...layers },
};
and you dispatch an action on a button that reduces the state to a new mapZoom object. That new state fires the native mapping library, wrapped in the react component to something like map.zoomTo(this.props.mapZoom)
.
Upvotes: 2