diff --git a/src/engine/blocks.js b/src/engine/blocks.js
index 8234a6e24..16bcd35b1 100644
--- a/src/engine/blocks.js
+++ b/src/engine/blocks.js
@@ -522,18 +522,21 @@ class Blocks {
             block.targetId = isSpriteSpecific ? optRuntime.getEditingTarget().id : null;
 
             if (wasMonitored && !block.isMonitored) {
-                optRuntime.requestRemoveMonitor(block.id);
+                optRuntime.requestHideMonitor(block.id);
             } else if (!wasMonitored && block.isMonitored) {
-                optRuntime.requestAddMonitor(MonitorRecord({
-                    id: block.id,
-                    targetId: block.targetId,
-                    spriteName: block.targetId ? optRuntime.getTargetById(block.targetId).getName() : null,
-                    opcode: block.opcode,
-                    params: this._getBlockParams(block),
-                    // @todo(vm#565) for numerical values with decimals, some countries use comma
-                    value: '',
-                    mode: block.opcode === 'data_listcontents' ? 'list' : 'default'
-                }));
+                // Tries to show the monitor for specified block. If it doesn't exist, add the monitor.
+                if (!optRuntime.requestShowMonitor(block.id)) {
+                    optRuntime.requestAddMonitor(MonitorRecord({
+                        id: block.id,
+                        targetId: block.targetId,
+                        spriteName: block.targetId ? optRuntime.getTargetById(block.targetId).getName() : null,
+                        opcode: block.opcode,
+                        params: this._getBlockParams(block),
+                        // @todo(vm#565) for numerical values with decimals, some countries use comma
+                        value: '',
+                        mode: block.opcode === 'data_listcontents' ? 'list' : 'default'
+                    }));
+                }
             }
             break;
         }
diff --git a/src/engine/runtime.js b/src/engine/runtime.js
index ab38955e4..cf6d90a67 100644
--- a/src/engine/runtime.js
+++ b/src/engine/runtime.js
@@ -1518,26 +1518,38 @@ class Runtime extends EventEmitter {
 
     /**
      * Add a monitor to the state. If the monitor already exists in the state,
-     * overwrites it.
+     * updates those properties that are defined in the given monitor record.
      * @param {!MonitorRecord} monitor Monitor to add.
      */
     requestAddMonitor (monitor) {
-        this._monitorState = this._monitorState.set(monitor.get('id'), monitor);
+        const id = monitor.get('id');
+        if (!this.requestUpdateMonitor(monitor)) { // update monitor if it exists in the state
+            // if the monitor did not exist in the state, add it
+            this._monitorState = this._monitorState.set(id, monitor);
+        }
     }
 
     /**
-     * Update a monitor in the state. Does nothing if the monitor does not already
-     * exist in the state.
+     * Update a monitor in the state and report success/failure of update.
      * @param {!Map} monitor Monitor values to update. Values on the monitor with overwrite
      *     values on the old monitor with the same ID. If a value isn't defined on the new monitor,
      *     the old monitor will keep its old value.
+     * @return {boolean} true if monitor exists in the state and was updated, false if it did not exist.
      */
     requestUpdateMonitor (monitor) {
         const id = monitor.get('id');
         if (this._monitorState.has(id)) {
             this._monitorState =
-                this._monitorState.set(id, this._monitorState.get(id).merge(monitor));
+                // Use mergeWith here to prevent undefined values from overwriting existing ones
+                this._monitorState.set(id, this._monitorState.get(id).mergeWith((prev, next) => {
+                    if (typeof next === 'undefined' || next === null) {
+                        return prev;
+                    }
+                    return next;
+                }, monitor));
+            return true;
         }
+        return false;
     }
 
     /**
@@ -1549,6 +1561,31 @@ class Runtime extends EventEmitter {
         this._monitorState = this._monitorState.delete(monitorId);
     }
 
+    /**
+     * Hides a monitor and returns success/failure of action.
+     * @param {!string} monitorId ID of the monitor to hide.
+     * @return {boolean} true if monitor exists and was updated, false otherwise
+     */
+    requestHideMonitor (monitorId) {
+        return this.requestUpdateMonitor(new Map([
+            ['id', monitorId],
+            ['visible', false]
+        ]));
+    }
+
+    /**
+     * Shows a monitor and returns success/failure of action.
+     * not exist in the state.
+     * @param {!string} monitorId ID of the monitor to show.
+     * @return {boolean} true if monitor exists and was updated, false otherwise
+     */
+    requestShowMonitor (monitorId) {
+        return this.requestUpdateMonitor(new Map([
+            ['id', monitorId],
+            ['visible', true]
+        ]));
+    }
+
     /**
      * Removes all monitors with the given target ID from the state. Does nothing if
      * the monitor already does not exist in the state.