 
 (defonce ^:dynamic *debug* (atom false))
 
+(defn- equals?
+  [np op]
+  (let [n-shape (unchecked-get np "shape")
+        o-shape (unchecked-get op "shape")
+        n-frame (unchecked-get np "frame")
+        o-frame (unchecked-get op "frame")]
+    (and (= n-frame o-frame)
+         (= n-shape o-shape))))
+
 (declare translate-to-frame)
 (declare group-shape)
 
-(defn group-wrapper [shape-wrapper]
-  (mf/fnc group-wrapper
-   {::mf/wrap-props false}
-   [props]
-   (let [shape (unchecked-get props "shape")
-         frame (unchecked-get props "frame")
-         on-mouse-down #(common/on-mouse-down % shape)
-         on-context-menu #(common/on-context-menu % shape)
-         children (-> (refs/objects-by-id (:shapes shape)) mf/deref)
-         is-child-selected? (-> (refs/is-child-selected? (:id shape)) mf/deref)
-         on-double-click
-         (fn [event]
-           (dom/stop-propagation event)
-           (dom/prevent-default event)
-           (st/emit! (dw/select-inside-group
-                      (:id shape)
-                      @ms/mouse-position)))]
+(defn group-wrapper
+  [shape-wrapper]
+  (let [group-shape (group-shape shape-wrapper)]
+    (mf/fnc group-wrapper
+      {::mf/wrap [#(mf/memo' % equals?)]
+       ::mf/wrap-props false}
+      [props]
+      (let [shape (unchecked-get props "shape")
+            frame (unchecked-get props "frame")
+            on-mouse-down   (mf/use-callback (mf/deps shape)
+                                             #(common/on-mouse-down % shape))
+            on-context-menu (mf/use-callback (mf/deps shape)
+                                             #(common/on-context-menu % shape))
 
-     [:g.shape {:on-mouse-down on-mouse-down
-                :on-context-menu on-context-menu
-                :on-double-click on-double-click}
-      [:& (group-shape shape-wrapper) {:frame frame
-                                       :shape (geom/transform-shape frame shape)
-                                       :children children
-                                       :is-child-selected? is-child-selected?}]])))
+            children-ref   (mf/use-memo (mf/deps shape)
+                                        #(refs/objects-by-id (:shapes shape)))
+            children       (mf/deref children-ref)
 
-(defn group-shape [shape-wrapper]
+
+            is-child-selected-ref (mf/use-memo (mf/deps (:id shape))
+                                               #(refs/is-child-selected? (:id shape)))
+            is-child-selected?    (mf/deref is-child-selected-ref)
+
+            on-double-click
+            (mf/use-callback
+             (mf/deps (:id shape))
+             (fn [event]
+               (dom/stop-propagation event)
+               (dom/prevent-default event)
+               (st/emit! (dw/select-inside-group (:id shape) @ms/mouse-position))))]
+
+        [:g.shape
+         {:on-mouse-down on-mouse-down
+          :on-context-menu on-context-menu
+          :on-double-click on-double-click}
+
+         [:& group-shape
+          {:frame frame
+           :shape (geom/transform-shape frame shape)
+           :children children
+           :is-child-selected? is-child-selected?}]]))))
+
+(defn group-shape
+  [shape-wrapper]
   (mf/fnc group-shape
     {::mf/wrap-props false}
     [props]

;; License, v. 2.0. If a copy of the MPL was not distributed with this
;; file, You can obtain one at http://mozilla.org/MPL/2.0/.
;;
;; Copyright (c) 2016-2019 Andrey Antukh <niwi@niwi.nz>

(ns uxbox.main.ui.shapes.group
  (:require

                                  (+ y (/ height 2))))]
      [:g {:transform transform}
       (for [item children]
         [:& shape-wrapper
          {:frame frame
           :shape (cond-> item
                    displacement-modifier (assoc :displacement-modifier displacement-modifier)
                    resize-modifier (assoc :resize-modifier resize-modifier))
           :key (:id item)}])

       (when (not is-child-selected?)
         [:rect {:x x
                 :y y
