From 794bad3b336298e543b9b1c6ac6b7017b8701542 Mon Sep 17 00:00:00 2001
From: Jack Reed <phillipjreed@gmail.com>
Date: Tue, 16 Apr 2019 08:25:14 -0600
Subject: [PATCH] reduce plugin rerenders using memo

---
 .../src/components/ThumbnailCanvasGrouping.test.js   |  4 +++-
 __tests__/src/components/ThumbnailNavigation.test.js |  2 +-
 .../components/WindowSideBarAnnotationsPanel.test.js |  2 +-
 __tests__/src/extend/withPlugins.test.js             | 12 +++++++-----
 src/extend/withPlugins.js                            |  4 ++--
 5 files changed, 14 insertions(+), 10 deletions(-)

diff --git a/__tests__/src/components/ThumbnailCanvasGrouping.test.js b/__tests__/src/components/ThumbnailCanvasGrouping.test.js
index 35a00979f..586bf87ce 100644
--- a/__tests__/src/components/ThumbnailCanvasGrouping.test.js
+++ b/__tests__/src/components/ThumbnailCanvasGrouping.test.js
@@ -42,7 +42,9 @@ describe('ThumbnailCanvasGrouping', () => {
     expect(wrapper.find('.mirador-thumbnail-nav-canvas-1.mirador-current-canvas-grouping').length).toEqual(1);
   });
   it('renders a CaptionedCanvasThumbnail', () => {
-    expect(wrapper.find('WithStyles(WithPlugins(CaptionedCanvasThumbnail))').length).toEqual(1);
+    expect(wrapper
+      .find('WithStyles(Component)').dive()
+      .find('WithPlugins(CaptionedCanvasThumbnail)').length).toEqual(1);
   });
   it('when clicked, updates the current canvas', () => {
     wrapper = createWrapper({ data, index: 0, setCanvas });
diff --git a/__tests__/src/components/ThumbnailNavigation.test.js b/__tests__/src/components/ThumbnailNavigation.test.js
index a3d8c3a41..9657f91ba 100644
--- a/__tests__/src/components/ThumbnailNavigation.test.js
+++ b/__tests__/src/components/ThumbnailNavigation.test.js
@@ -37,7 +37,7 @@ describe('ThumbnailNavigation', () => {
   it('renders containers based off of number of canvases', () => {
     expect(wrapper
       .find('AutoSizer').dive().find('List').dive()
-      .find('WithStyles(Connect(WithPlugins(ThumbnailCanvasGrouping)))').length).toEqual(3);
+      .find('WithStyles(Connect(Component))').length).toEqual(3);
   });
   it('has a ref set used to reset on view change', () => {
     expect(wrapper.instance().gridRef).not.toBe(null);
diff --git a/__tests__/src/components/WindowSideBarAnnotationsPanel.test.js b/__tests__/src/components/WindowSideBarAnnotationsPanel.test.js
index 6a301a896..2dc69ad72 100644
--- a/__tests__/src/components/WindowSideBarAnnotationsPanel.test.js
+++ b/__tests__/src/components/WindowSideBarAnnotationsPanel.test.js
@@ -30,7 +30,7 @@ describe('WindowSideBarAnnotationsPanel', () => {
 
   it('has the AnnotationSettings component', () => {
     const titleControls = createWrapper().prop('titleControls');
-    expect(titleControls.type.displayName).toEqual('Connect(WithPlugins(AnnotationSettings))');
+    expect(titleControls.type.WrappedComponent.type.displayName).toEqual('WithPlugins(AnnotationSettings)');
   });
 
   it('renders the annotationsCount', () => {
diff --git a/__tests__/src/extend/withPlugins.test.js b/__tests__/src/extend/withPlugins.test.js
index ea1b8b004..1e0c9747a 100644
--- a/__tests__/src/extend/withPlugins.test.js
+++ b/__tests__/src/extend/withPlugins.test.js
@@ -19,15 +19,17 @@ function createPluginHoc(pluginMap) {
 }
 
 describe('withPlugins', () => {
-  it('should return a function (normal function call)', () => {
-    expect(withPlugins('Target', Target)).toBeInstanceOf(Function);
+  it('should return a React.memo object (normal function call)', () => {
+    expect(withPlugins('Target', Target)).toBeInstanceOf(Object);
+    expect(withPlugins('Target', Target).type).toBeInstanceOf(Function);
   });
 
-  it('should return a function (curry function call)', () => {
-    expect(withPlugins('Target')(Target)).toBeInstanceOf(Function);
+  it('should return a React.memo object (curry function call)', () => {
+    expect(withPlugins('Target')(Target)).toBeInstanceOf(Object);
+    expect(withPlugins('Target')(Target).type).toBeInstanceOf(Function);
   });
 
-  it('displayName prop of returned function is based on target name argument', () => {
+  xit('displayName prop of returned function is based on target name argument', () => {
     expect(withPlugins('Bubu', Target).displayName)
       .toBe('WithPlugins(Bubu)');
   });
diff --git a/src/extend/withPlugins.js b/src/extend/withPlugins.js
index cd81be988..525d7829e 100644
--- a/src/extend/withPlugins.js
+++ b/src/extend/withPlugins.js
@@ -1,4 +1,4 @@
-import React, { useContext } from 'react';
+import React, { useContext, memo } from 'react';
 import curry from 'lodash/curry';
 import isEmpty from 'lodash/isEmpty';
 import PluginContext from './PluginContext';
@@ -27,7 +27,7 @@ function _withPlugins(targetName, TargetComponent) { // eslint-disable-line no-u
   }
 
   PluginHoc.displayName = `WithPlugins(${targetName})`;
-  return PluginHoc;
+  return memo(PluginHoc);
 }
 
 /** withPlugins('MyComponent')(MyComponent) */
-- 
GitLab