diff --git a/__tests__/src/selectors/manifests.test.js b/__tests__/src/selectors/manifests.test.js
index da4460884ca402fe9b128248b39f7aa32f4d2ab1..d94344acc7b680eb7fe05c5daa5149a920531b2f 100644
--- a/__tests__/src/selectors/manifests.test.js
+++ b/__tests__/src/selectors/manifests.test.js
@@ -81,6 +81,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 22dec14f43c3f84c3880cd64c2917336122a9a50..909f59f87d694f0d54c44df665f47cea63bd1391 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 1af414a3b5f7e87cdca9d72c6c277c2c8e042074..7b8cd353ef174a79983ec1d024e6c19280163f7a 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(