diff --git a/__tests__/src/selectors/manifests.test.js b/__tests__/src/selectors/manifests.test.js
index 3e4b4d9415d55f0466914a976b3f252bea722525..6135c9da20bce4828f60883efc592533e1b845c5 100644
--- a/__tests__/src/selectors/manifests.test.js
+++ b/__tests__/src/selectors/manifests.test.js
@@ -80,6 +80,12 @@ describe('getManifestoInstance', () => {
     const received = getManifestoInstance(state, { manifestId: 'x' });
     expect(received.id).toEqual('http://iiif.io/api/presentation/2.1/example/fixtures/19/manifest.json');
   });
+  it('is cached based off of input props', () => {
+    const state = { manifests: { x: { json: manifestFixture019 } } };
+    const received = getManifestoInstance(state, { manifestId: 'x' });
+    expect(getManifestoInstance(state, { manifestId: 'x' })).toBe(received);
+    expect(getManifestoInstance(state, { manifestId: 'x', windowId: 'y' })).not.toBe(received);
+  });
 });
 
 describe('getManifestLogo()', () => {
diff --git a/package.json b/package.json
index 5905712ec12fa6fa600e999b85cf1a533c1d87f1..6c1617f5aae652fa38df962d1ac1006269929d35 100644
--- a/package.json
+++ b/package.json
@@ -49,6 +49,7 @@
     "normalize-url": "^4.2.0",
     "openseadragon": "^2.4.1",
     "prop-types": "^15.6.2",
+    "re-reselect": "^3.4.0",
     "react-aria-live": "^2.0.5",
     "react-copy-to-clipboard": "^5.0.1",
     "react-full-screen": "^0.2.4",
diff --git a/src/state/selectors/manifests.js b/src/state/selectors/manifests.js
index e6fe70f08dd523d433db09a495d8c8b4de2f7a8e..4f63393b2277c7d052d541158023c3d43e491389 100644
--- a/src/state/selectors/manifests.js
+++ b/src/state/selectors/manifests.js
@@ -1,4 +1,5 @@
 import { createSelector } from 'reselect';
+import createCachedSelector from 're-reselect';
 import manifesto, { LanguageMap } from 'manifesto.js';
 import ManifestoCanvas from '../../lib/ManifestoCanvas';
 
@@ -18,13 +19,20 @@ export function getManifest(state, { manifestId, windowId }) {
 }
 
 /** Instantiate a manifesto instance */
-export const getManifestoInstance = createSelector(
-  [
-    getManifest,
-    getLocale,
-  ],
+export const getManifestoInstance = createCachedSelector(
+  getManifest,
+  getLocale,
   (manifest, locale) => manifest
     && createManifestoInstance(manifest.json, locale),
+)(
+  (state, props) => [
+    props.manifestId,
+    props.windowId,
+    (state.companionWindows
+      && state.companionWindows[props.companionWindowId]
+      && state.companionWindows[props.companionWindowId].locale)
+      || (state.config && state.config.language),
+  ].join(' - '), // Cache key consisting of manifestId, windowId, and locale
 );
 
 export const getManifestLocale = createSelector(