Summary
In a previous post I discussed a pattern for implementing maps in React based web applications using a pub/sub approach. This post expands on the idea, presenting a complementary approach using the command pattern.
The basic problem is that the state driven approach of React.js is at odds with API approach of web map components.
Using the command pattern allows encapsulation of the logic to drive the map making the map component itself very simple.
Implementation
All samples are provided in React.js using Typescript with the OpenLayers map control.
I have found an approach that works well when building web based map applications in React.js. I’ve found in the past that map components can get very complicated very quickly making the map control hard to maintain and hard to add new features to.
This solution is based around the command pattern, where operations performed on the map are encapsulated in classes. These classes have a common interface requiring a single ‘execute’ method:
I initially used ‘context’ as I thought I would have to attach additional map objects (such as views and layers) for commands to use, but I found in practice this wasn’t necessary. I kept it for clarity.
This allows us to have a very simple map component. An array of commands are passed in as props. They are executed in turn once the map has been created.
So what does a command do and what does it look like?
Well a command can contain any operation that you may wish to perform on the map. Let’s take adjusting the zoom level as an initial example:
In this case when the map component calls ‘execute’ the command keeps a reference to the map object. The command exposes a ‘zoom’ method which will then adjust the zoom level on the map accordingly.
This is a simple example, how about something more interesting?
This example will add features to the map:
One final example which is to respond to map clicks and call a function back when a feature is selected:
To add the map component to a page you simply create the commands and pass them in as props:
Methods to manipulate the map can be coupled to a pub/sub system as mentioned in my previous blog post.
Conclusion
The command pattern seems to be a nice way to reduce the complexity of implementing map components in web applications.
I have used this approach on a couple of recent projects with some complicated interactions such as drawing geofences, adding/removing tile layers, and display additional controls on the map. Everything I have tried seems to have worked out easily, which is a good confirmation that the pattern is well suited to this task.
I particularly like the encapsulation of all the boiler plate that open layers requires when dealing with the map and exposing higher order ‘business’ functions to the consumer.
Commands are highly reusable between different parts of your application, or different applications.
Perhaps a library of these commands could be built to accelerate map projects.