Main Frontend Technologies
The main tecnologies used on the mapstore 2 are:
- ReactJS (View)
- Redux (state management)
ReactJS 0.16.x is used to develop MapStore. The main purpose of ReactJS is to allow writing the View of the application, through the composition of small components, in a declarative way.
ReactJS component example
1 2 3 4 5
Properties, State and Event handlers
Components can define and use properties, like the title one used in the example. These are immutable, and cannot be changed by component's code.
Components can also use state that can change. When the state changes, the component is updated (re-rendered) automatically.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
In this example, the initial state includes a title property whose value is
When the h1 element is clicked, the state is changed so that title becomes
The HTML page is automatically updated by ReactJS, each time the state changes (each time this.setState is called). For this reason we say that JSX allows to declaratively describe the View for each possible application state.
Components can re-define some lifecycle methods, to execute actions in certain moments of the component life. Lifecycle API is changed in react 16 so please refer to the official documentation.
Redux promotes a unidirectional dataflow (inspired by the Flux architecture) and immutable state transformation using reducers, to achieve predictable and reproducable application behaviour.
A single, global, Store is delegated to contain all the application state.
The state can be changed dispatching Actions to the store.
Each action produces a new state (the state is never changed, a new state is produced and that is the new application state), through the usage of one or more reducers.
(Smart) Components can be connected to the store and be notified when the state changes, so that views are automatically updated.
In Redux, actions are actions descriptors, generated by an action creator. Actions descriptors are usually defined by an action type and a set of parameters that specify the action payload.
1 2 3 4 5 6 7 8 9
Reducers are functions that receive an action and the current state and:
- produce a new state, for each recognized action
- produce the current state for unrecognized actions
- produce initial state, if the current state is undefined
1 2 3 4 5 6 7 8
The redux store combines different reducers to produce a global state, with a slice for each used reducer.
1 2 3 4 5 6 7
The Redux store receives actions, through a dispatch method, and creates a new application state, using the configured reducers.
You can subscribe to the store, to be notified whenever the state changes.
Redux data flow is synchronous. To provide asynchronous functionalities (e.g. Ajax) redux needs a middleware. Actually MapStore uses 2 middlewares for this purpose:
- Redux thunk (going to be fully replaced by redux-observable)
- Redux Observable
This middleware allows to perform simple asynchronous flows by returning a function from the action creator (instead of a action object).
1 2 3 4 5 6 7 8 9 10 11
This middleware is there from the beginning of the MapStore history. During the years, some better middlewares have been developed for this purpose. We want to replace it in the future with redux-observable.
Redux Observable and epics
This middleware provides support for side-effects in MapStore using rxjs. The core object of this middleware is the
The epic is a function that simply gets as first parameter an
Observable (stream) emitting the actions emitted by redux. It returns another
Observable (stream) that emits actions that will be forwarded to redux too.
So there are 2 streams:
- Actions in
- Actions out
A simple epic example can be the following:
1 2 3
Every time a 'PING' action is emitted, the epic will emit also the 'PONG' action.
- Introduction to RxJS for MapStore Developers
- redux-observable site
- rxjs Observable as a reference for methods
- setting up the middleware to integrate epics with your store
Redux and ReactJS integration
The react-redux library can be used to connect the Redux application state to ReactJS components.
This can be done in the following way:
- wrap the ReactJS root component with the react-redux Provider component, to bind the Redux store to the ReactJS view
1 2 3 4 5 6
- explicitly connect one or more (smart) components to a all or part of the state (you can also transform the state and have computed properties)
1 2 3 4 5 6
The connected component will get automatic access to the configured slice through properties:
1 2 3