I would like to share my experience building a React Redux app with the ArcGIS API for JavaScript (ArcGIS JS API). It is exciting how well these work together. I will also share some boilerplate source code to help you get started with your own React Redux ArcGIS application.
There are a number of reasons to take a closer look at the React Redux framework:
- It’s hot (both literally and figuratively speaking). More on Hot Module Replacement below.
- There’s total separation of data and presentation.
- Redux makes state management more predictable (fewer bugs!)
- React provides reusable UI components, blazing fast performance, and support for mobile (React Native) and server side rendering.
Crash Course: React + Redux
Before we start, here is a very quick intro to React and Redux.
The Redux Store keeps the application state. This state can be updated by dispatching actions. An action is nothing more than a JSON object with a type and some parameters (e.g., { type: ‘SET_DATE’, date: ‘2017-03-15T13:24:00.000Z’ }). The store has a reducer, which, taking into account the action and the previous state, will produce the next state.
React lets you build components that react to changes of the application state. Components affected by a state change are re-rendered with the new data. Components also dispatch actions, for example when a button is clicked.
The Demo App
To demonstrate the basics, I created a demo app that lets users sign in with their ArcGIS Online account and open a scene. I added a simple selection tool (Ctrl to select multiple features) and a simple sun position slider.
The source code and installation instructions are available on GitHub.
Software Architecture
The application is a textbook React Redux app as you would find in many tutorials. It has the usual structure of components and reducers. To make this possible, I have encapsulated the ArcGIS JS API in a middleware. I have implemented one middleware for the ArcGIS Online authentication, and another one for the SceneView.
The middleware intercepts actions, interacts with the ArcGIS JS API if necessary, then forwards the action or dispatches new actions. This pattern provides a nice encapsulation for store behavior that does not form part of the data. In other words, it keeps non-data objects out of the store (e.g., instances of esri/views/SceneView) and makes testing a lot easier.
Learn more: You Aren’t Using Redux Middleware Enough.
The Magic Sauce
What is the magical part of the configuration that makes the Esri modules directly accessible in the project? On one hand, we have a pure React Redux app; on the other hand, we are loading Esri modules as if they are right there in the project structure.
This works because we compile and pack the React Redux app with all its dependencies into a single AMD module. However, all Esri modules are automatically marked as external and skipped in this process. The ArcGIS JS API then runs the resulting AMD module as the main application, which makes the Esri dependencies available to the app.
Redux Dev Tools Extension
One of the greatest things about Redux is the Dev Tools Extension. This extension lets you inspect the application state live as it updates, and it lets you dispatch actions from the console. This is great for rapid prototyping: you don’t have to build a UI to test a feature.
For example, when developing the sun position slider, I first implemented the SET_DATE action, and added the corresponding environment updates in the SceneView middleware. I could then try to change the sun position by dispatching SET_DATE actions from the console, and see the state update accordingly. Once that was working correctly, I implemented a range slider component to dispatch those same actions.
Hot Module Replacement
Hot Module Replacement exchanges, adds, or removes modules while an application is running, without a full reload. This has numerous benefits for development:
- Application state is retained, which is lost during a full reload.
- You save development time by only reloading part of the application (e.g., don’t wait for the SceneView to reload).
- The UI can be tweaked quickly, in real time (fast prototyping).
How it works: when a module is updated, the front end is notified and downloads the changes. For components, the application DOM is refreshed with the updated component. For reducers, the application store replaces its reducer with the updated reducer.
Looking closer, refreshing the DOM would inevitably reload the SceneView after each component update. To prevent this from happening, the SceneView is created and stored in the middleware. In fact, the middleware stores both a SceneView object and its container element. On refresh, the existing container is automatically attached to the refreshed React component.
Learn more: Hot Module Replacement
Testing
React makes front end testing a breeze. Components can be tested using Jest and Enzyme. Jest is an awesome testing tool developed by Facebook. Enzyme sits on top and is a testing utility for React developed by Airbnb. The combination of React and Enzyme is a game changer.
You can do shallow tests to check if everything is rendered OK and the right actions are dispatched when clicked. You can do deep tests to check if several components are loaded together correctly. It allows for an unprecedented level of front end testing.
To get you started, I have added some Jest and Enzyme tests to every module of the boilerplate.
Learn More: Writing Tests – Redux, Jest, Enzyme
Build Process
Building the application has been a challenge due to the ArcGIS JS API‘s dependency on Dojo. Nevertheless, there exists a very elegant solution.
The React Redux app is compiled and packed into an AMD module, which fits into the Dojo toolkit. We use Babel to transpile ES6 to regular JavaScript, and then Webpack to bundle the application into a single AMD module. However, we use a regular expression to exclude all Esri modules from this build process.
The ArcGIS JS API loads the resulting module as the main application (as defined in dojoConfig.js). This makes the Esri dependencies available to the app and allows everything to run smoothly.
Resources
React Redux JS4 Boilerplate on Github
Credits
To code this boilerplate application, I have used this work by Rene Rubalcava as a starting point.
Commenting is not enabled for this article.