diff --git a/__tests__/src/components/ThumbnailCanvasGrouping.test.js b/__tests__/src/components/ThumbnailCanvasGrouping.test.js
index dfcfcb7312159ae3d22e1b8fbf7c73ffaf003c2d..ba27c5a71cbeaeab2f1a0c60f4c0c81271ef5ff8 100644
--- a/__tests__/src/components/ThumbnailCanvasGrouping.test.js
+++ b/__tests__/src/components/ThumbnailCanvasGrouping.test.js
@@ -28,7 +28,7 @@ describe('ThumbnailCanvasGrouping', () => {
   let setCanvas;
   const data = {
     canvasGroupings: new CanvasGroupings(Utils.parseManifest(manifestJson)
-      .getSequences()[0].getCanvases()),
+      .getSequences()[0].getCanvases()).groupings(),
     height: 131,
     position: 'far-bottom',
   };
diff --git a/__tests__/src/components/ThumbnailNavigation.test.js b/__tests__/src/components/ThumbnailNavigation.test.js
index e86aa08966ab0bf28fc79e3e42d9d3f2986fc5c4..4bfbf173ff2859e039055e7ee0f7b78d9a7b9952 100644
--- a/__tests__/src/components/ThumbnailNavigation.test.js
+++ b/__tests__/src/components/ThumbnailNavigation.test.js
@@ -12,7 +12,9 @@ function createWrapper(props, fixture = manifestJson) {
   return shallow(
     <ThumbnailNavigation
       canvasGroupings={
-        new CanvasGroupings(Utils.parseManifest(fixture).getSequences()[0].getCanvases())
+        new CanvasGroupings(
+          Utils.parseManifest(fixture).getSequences()[0].getCanvases(),
+        ).groupings()
       }
       canvasIndex={1}
       classes={{}}
diff --git a/src/components/CanvasLayers.js b/src/components/CanvasLayers.js
index 7024334c49909bb7b1f6b92c6d4e9b3264c413ec..d2eb7d44d8e1aa471a211b3fc14955006f290e14 100644
--- a/src/components/CanvasLayers.js
+++ b/src/components/CanvasLayers.js
@@ -51,7 +51,7 @@ export class CanvasLayers extends Component {
   /** */
   onDragEnd(result) {
     const {
-      canvas, layers, updateLayers, windowId,
+      canvasId, layers, updateLayers, windowId,
     } = this.props;
     if (!result.destination) return;
     if (result.destination.droppableId !== this.droppableId) return;
@@ -68,26 +68,26 @@ export class CanvasLayers extends Component {
       return acc;
     }, {});
 
-    updateLayers(windowId, canvas.id, payload);
+    updateLayers(windowId, canvasId, payload);
   }
 
   /** */
   setLayerVisibility(layerId, value) {
     const {
-      canvas, updateLayers, windowId,
+      canvasId, updateLayers, windowId,
     } = this.props;
 
     const payload = {
       [layerId]: { visibility: value },
     };
 
-    updateLayers(windowId, canvas.id, payload);
+    updateLayers(windowId, canvasId, payload);
   }
 
   /** */
   moveToTop(layerId) {
     const {
-      canvas, layers, updateLayers, windowId,
+      canvasId, layers, updateLayers, windowId,
     } = this.props;
 
     const sortedLayers = reorder(layers.map(l => l.id), layers.findIndex(l => l.id === layerId), 0);
@@ -97,20 +97,20 @@ export class CanvasLayers extends Component {
       return acc;
     }, {});
 
-    updateLayers(windowId, canvas.id, payload);
+    updateLayers(windowId, canvasId, payload);
   }
 
   /** */
   handleOpacityChange(layerId, value) {
     const {
-      canvas, updateLayers, windowId,
+      canvasId, updateLayers, windowId,
     } = this.props;
 
     const payload = {
       [layerId]: { opacity: value / 100.0 },
     };
 
-    updateLayers(windowId, canvas.id, payload);
+    updateLayers(windowId, canvasId, payload);
   }
 
   /** @private */
@@ -261,9 +261,7 @@ export class CanvasLayers extends Component {
 }
 
 CanvasLayers.propTypes = {
-  canvas: PropTypes.shape({
-    id: PropTypes.string,
-  }).isRequired,
+  canvasId: PropTypes.string.isRequired,
   classes: PropTypes.objectOf(PropTypes.string),
   index: PropTypes.number.isRequired,
   label: PropTypes.string.isRequired,
diff --git a/src/components/ThumbnailCanvasGrouping.js b/src/components/ThumbnailCanvasGrouping.js
index 958e2e5f2a4d10e31a48a932f5b4f878ec06da50..cc966ff815eba1093a823238a750ce70f5ac309c 100644
--- a/src/components/ThumbnailCanvasGrouping.js
+++ b/src/components/ThumbnailCanvasGrouping.js
@@ -36,7 +36,7 @@ export class ThumbnailCanvasGrouping extends PureComponent {
     const {
       canvasGroupings, position, height,
     } = data;
-    const currentGroupings = canvasGroupings.groupings()[index];
+    const currentGroupings = canvasGroupings[index];
     const SPACING = 8;
     return (
       <div
diff --git a/src/components/ThumbnailNavigation.js b/src/components/ThumbnailNavigation.js
index 48accae8e21f7708b802ab5d503cea106392a211..252e458243868b6f5b6c6ece55639dd510548595 100644
--- a/src/components/ThumbnailNavigation.js
+++ b/src/components/ThumbnailNavigation.js
@@ -48,7 +48,7 @@ export class ThumbnailNavigation extends Component {
    */
   calculateScaledSize(index) {
     const { thumbnailNavigation, canvasGroupings, position } = this.props;
-    const canvases = canvasGroupings.groupings()[index];
+    const canvases = canvasGroupings[index];
     const world = new CanvasWorld(canvases);
     const bounds = world.worldBounds();
     switch (position) {
@@ -125,7 +125,7 @@ export class ThumbnailNavigation extends Component {
   /** */
   itemCount() {
     const { canvasGroupings } = this.props;
-    return canvasGroupings.groupings().length;
+    return canvasGroupings.length;
   }
 
   /** */
@@ -231,7 +231,7 @@ export class ThumbnailNavigation extends Component {
 }
 
 ThumbnailNavigation.propTypes = {
-  canvasGroupings: PropTypes.object.isRequired, // eslint-disable-line react/forbid-prop-types
+  canvasGroupings: PropTypes.array.isRequired, // eslint-disable-line react/forbid-prop-types
   canvasIndex: PropTypes.number.isRequired,
   classes: PropTypes.objectOf(PropTypes.string).isRequired,
   hasNextCanvas: PropTypes.bool,
diff --git a/src/containers/CanvasLayers.js b/src/containers/CanvasLayers.js
index 7e36dc1d6f52f381037ae086f9cb9df7226c773d..aba5f5c7c7703a0f989801e99022498742ca27cf 100644
--- a/src/containers/CanvasLayers.js
+++ b/src/containers/CanvasLayers.js
@@ -4,7 +4,6 @@ import { withTranslation } from 'react-i18next';
 import { withStyles } from '@material-ui/core/styles';
 import * as actions from '../state/actions';
 import {
-  getCanvas,
   getCanvasLabel,
   getLayers,
   getSortedLayers,
@@ -13,11 +12,7 @@ import { CanvasLayers } from '../components/CanvasLayers';
 
 /** For connect */
 const mapStateToProps = (state, { canvasId, windowId }) => ({
-  canvas: getCanvas(state, { canvasId, windowId }),
-  label: getCanvasLabel(state, {
-    canvasId,
-    windowId,
-  }),
+  label: getCanvasLabel(state, { canvasId, windowId }),
   layerMetadata: getLayers(state, { canvasId, windowId }),
   layers: getSortedLayers(state, { canvasId, windowId }),
 });
diff --git a/src/containers/ThumbnailNavigation.js b/src/containers/ThumbnailNavigation.js
index eb82793df90cd4a35c6432dfe4b9a59d339bd6cb..e3be9a8f3363f1068771976c0d71929445d9e771 100644
--- a/src/containers/ThumbnailNavigation.js
+++ b/src/containers/ThumbnailNavigation.js
@@ -3,13 +3,12 @@ import { connect } from 'react-redux';
 import { withTranslation } from 'react-i18next';
 import { withStyles } from '@material-ui/core/styles';
 import { withPlugins } from '../extend/withPlugins';
-import CanvasGroupings from '../lib/CanvasGroupings';
 import * as actions from '../state/actions';
 import { ThumbnailNavigation } from '../components/ThumbnailNavigation';
 import {
   getCompanionWindow, getWindow,
   getNextCanvasGrouping, getPreviousCanvasGrouping,
-  getCanvases, getCanvasIndex, getWindowViewType,
+  getCanvasGroupings, getCanvasIndex, getWindowViewType,
   getSequenceViewingDirection, getConfig,
 } from '../state/selectors';
 
@@ -18,24 +17,18 @@ import {
  * @memberof ThumbnailNavigation
  * @private
  */
-const mapStateToProps = (state, { windowId }) => {
-  const viewType = getWindowViewType(state, { windowId });
-  return {
-    canvasGroupings: new CanvasGroupings(
-      getCanvases(state, { windowId }),
-      viewType,
-    ),
-    canvasIndex: getCanvasIndex(state, { windowId }),
-    hasNextCanvas: !!getNextCanvasGrouping(state, { windowId }),
-    hasPreviousCanvas: !!getPreviousCanvasGrouping(state, { windowId }),
-    position: getCompanionWindow(state, {
-      companionWindowId: getWindow(state, { windowId }).thumbnailNavigationId,
-    }).position,
-    thumbnailNavigation: getConfig(state).thumbnailNavigation,
-    view: viewType,
-    viewingDirection: getSequenceViewingDirection(state, { windowId }),
-  };
-};
+const mapStateToProps = (state, { windowId }) => ({
+  canvasGroupings: getCanvasGroupings(state, { windowId }),
+  canvasIndex: getCanvasIndex(state, { windowId }),
+  hasNextCanvas: !!getNextCanvasGrouping(state, { windowId }),
+  hasPreviousCanvas: !!getPreviousCanvasGrouping(state, { windowId }),
+  position: getCompanionWindow(state, {
+    companionWindowId: getWindow(state, { windowId }).thumbnailNavigationId,
+  }).position,
+  thumbnailNavigation: getConfig(state).thumbnailNavigation,
+  view: getWindowViewType(state, { windowId }),
+  viewingDirection: getSequenceViewingDirection(state, { windowId }),
+});
 
 /**
  * mapDispatchToProps - used to hook up connect to action creators
diff --git a/src/state/selectors/canvases.js b/src/state/selectors/canvases.js
index 684676bcd8fb15756f7a5246b2c6b535ef12046c..4a3c9924889b25d1caa071bc965ae2a557d018a8 100644
--- a/src/state/selectors/canvases.js
+++ b/src/state/selectors/canvases.js
@@ -70,7 +70,7 @@ export const getVisibleCanvases = createSelector(
 * @param {string} props.windowId
 * @return {Array}
 */
-const getCanvasGroupings = createSelector(
+export const getCanvasGroupings = createSelector(
   [
     getCanvases,
     getWindowViewType,