diff --git a/package.json b/package.json
index eeabbe19feb400c151450533a50b8e8ddaa34392..3429ec678e7a3c0e3f8ab6b843dcb33def970d82 100644
--- a/package.json
+++ b/package.json
@@ -38,6 +38,7 @@
     "eslint-plugin-react": "^7.0.1",
     "gh-pages": "^1.0.0",
     "html-webpack-plugin": "2.28.0",
+    "immutable": "3.8.1",
     "lodash.bindall": "4.4.0",
     "lodash.debounce": "4.0.8",
     "lodash.defaultsdeep": "4.6.0",
diff --git a/src/components/monitor-list/monitor-list.jsx b/src/components/monitor-list/monitor-list.jsx
index 9ee885036cbf8d7b99ee790f2c6032afb8905192..fd9631e23fa06939794773814e8114d447cfc65f 100644
--- a/src/components/monitor-list/monitor-list.jsx
+++ b/src/components/monitor-list/monitor-list.jsx
@@ -2,6 +2,8 @@ const React = require('react');
 const Box = require('../box/box.jsx');
 const Monitor = require('../../containers/monitor.jsx');
 const PropTypes = require('prop-types');
+const {OrderedMap} = require('immutable');
+
 
 const styles = require('./monitor-list.css');
 
@@ -9,10 +11,14 @@ const MonitorList = props => (
     <Box
         className={styles.monitorList}
     >
-        {props.monitors.map(monitorData => (
+        {props.monitors.valueSeq().map((monitorData, index) => (
             <Monitor
-                {...monitorData}
+                id={monitorData.id}
+                index={index}
                 key={monitorData.id}
+                opcode={monitorData.opcode}
+                params={monitorData.params}
+                value={monitorData.value}
                 onDragEnd={props.onMonitorChange}
             />
         ))}
@@ -20,13 +26,7 @@ const MonitorList = props => (
 );
 
 MonitorList.propTypes = {
-    monitors: PropTypes.arrayOf(PropTypes.shape({
-        color: PropTypes.string,
-        label: PropTypes.string.isRequired,
-        value: PropTypes.string.isRequired,
-        x: PropTypes.number,
-        y: PropTypes.number
-    })),
+    monitors: PropTypes.instanceOf(OrderedMap),
     onMonitorChange: PropTypes.func.isRequired
 };
 
diff --git a/src/containers/monitor.jsx b/src/containers/monitor.jsx
index 4ec8681572efc567f9a54443f86d5199a8754f60..9bed328d40542625e0634961fb7729669269931e 100644
--- a/src/containers/monitor.jsx
+++ b/src/containers/monitor.jsx
@@ -1,6 +1,8 @@
 const bindAll = require('lodash.bindall');
 const React = require('react');
+const PropTypes = require('prop-types');
 
+const monitorAdapter = require('../lib/monitor-adapter.js');
 const MonitorComponent = require('../components/monitor/monitor.jsx');
 
 class Monitor extends React.Component {
@@ -18,15 +20,23 @@ class Monitor extends React.Component {
         );
     }
     render () {
+        const monitorProps = monitorAdapter(this.props);
         return (
             <MonitorComponent
-                {...this.props}
+                {...monitorProps}
                 onDragEnd={this.handleDragEnd}
             />
         );
     }
 }
 
-Monitor.propTypes = MonitorComponent.propTypes;
+Monitor.propTypes = {
+    id: PropTypes.string.isRequired,
+    index: PropTypes.number.isRequired, // eslint-disable-line react/no-unused-prop-types
+    onDragEnd: PropTypes.func.isRequired,
+    opcode: PropTypes.string.isRequired, // eslint-disable-line react/no-unused-prop-types
+    params: PropTypes.object, // eslint-disable-line react/no-unused-prop-types, react/forbid-prop-types
+    value: PropTypes.string.isRequired // eslint-disable-line react/no-unused-prop-types
+};
 
 module.exports = Monitor;
diff --git a/src/lib/monitor-adapter.js b/src/lib/monitor-adapter.js
index 8dcc802a48e9414062431e6ca9137f8d2eef6cde..dc66fd0b88c8273624ef0a07b30767add579ef51 100644
--- a/src/lib/monitor-adapter.js
+++ b/src/lib/monitor-adapter.js
@@ -3,14 +3,14 @@
  * - Convert opcode to a label and a category
  * - Add missing XY position data if needed
  */
-const OpcodeLabels = require('../lib/opcode-labels.js');
+const OpcodeLabels = require('./opcode-labels.js');
 
 const PADDING = 5;
 const MONITOR_HEIGHT = 23;
 
 const isUndefined = a => typeof a === 'undefined';
 
-module.exports = function ({id, opcode, params, value, x, y}, monitorIndex) {
+module.exports = function ({id, index, opcode, params, value, x, y}) {
     let {label, category, labelFn} = OpcodeLabels(opcode);
 
     // Use labelFn if provided for dynamic labelling (e.g. variables)
@@ -20,7 +20,7 @@ module.exports = function ({id, opcode, params, value, x, y}, monitorIndex) {
     // @todo scratch2 has a more complex layout behavior we may want to adopt
     // @todo e.g. this does not work well when monitors have already been moved
     if (isUndefined(x)) x = PADDING;
-    if (isUndefined(y)) y = PADDING + (monitorIndex * (PADDING + MONITOR_HEIGHT));
+    if (isUndefined(y)) y = PADDING + (index * (PADDING + MONITOR_HEIGHT));
 
     return {id, label, category, value, x, y};
 };
diff --git a/src/reducers/monitors.js b/src/reducers/monitors.js
index 18e9529f4ad417645101a5cc85ed60b6b8adecf0..e21e67a0193a5a1d40a9690a877d05cd75ca0aa4 100644
--- a/src/reducers/monitors.js
+++ b/src/reducers/monitors.js
@@ -1,14 +1,13 @@
-const monitorAdapter = require('../lib/monitor-adapter.js');
-
 const UPDATE_MONITORS = 'scratch-gui/monitors/UPDATE_MONITORS';
+const {OrderedMap} = require('immutable');
 
-const initialState = [];
+const initialState = OrderedMap();
 
 const reducer = function (state, action) {
     if (typeof state === 'undefined') state = initialState;
     switch (action.type) {
     case UPDATE_MONITORS:
-        return action.monitors.map(monitorAdapter);
+        return action.monitors;
     default:
         return state;
     }