Repository: penpot/penpot
File: frontend/src/app/main/ui/workspace/context_menu.cljs (ClojureScript)

Code before:
   [okulary.core :as l]
   [potok.v2.core :as ptk]
   [rumext.v2 :as mf]))

(def menu-ref
  (l/derived :context-menu refs/workspace-local))

(defn- prevent-default
  [event]
  (dom/prevent-default event)
  (dom/stop-propagation event))

(mf/defc menu-entry*
  {::mf/props :obj
   ::mf/private true}
  [{:keys [title shortcut on-click on-pointer-enter on-pointer-leave
           on-unmount children is-selected icon disabled value]}]
  (let [submenu-ref (mf/use-ref nil)
        hovering?   (mf/use-ref false)
        handle-menu-click
        (fn [on-click]
          (fn [event]
            (st/emit! dw/hide-context-menu)
            (when on-click (on-click event))))

        on-pointer-enter
        (mf/use-fn
         (fn []
           (mf/set-ref-val! hovering? true)
           (let [submenu-node (mf/ref-val submenu-ref)]
             (when (some? submenu-node)
               (dom/set-css-property! submenu-node "display" "block")))
           (when on-pointer-enter (on-pointer-enter))))

        on-pointer-leave
        (mf/use-fn
         (fn []
           (mf/set-ref-val! hovering? false)
           (let [submenu-node (mf/ref-val submenu-ref)]
             (when (some? submenu-node)
               (timers/schedule
                200
                #(when-not (mf/ref-val hovering?)
                   (dom/set-css-property! submenu-node "display" "none")))))
           (when on-pointer-leave (on-pointer-leave))))

        set-dom-node
        (mf/use-fn
         (fn [dom]
           (let [submenu-node (mf/ref-val submenu-ref)]
             (when (and (some? dom) (some? submenu-node))

Review comment (suggestion):
With that code you are generating a new callback each time you render a component, and this is a bad practice. It has no substantial relevance for this code, but I think we should avoid this kind of patters for avoid future copy paste.

I suggest using something like this:

```clojure
(let [on-click'
      (mf/use-fn
       (mf/deps on-click)
       (fn [event]
         (st/emit! dw/hide-context-menu)
         (when on-click
           (on-click event))))
      ...
```

Code after:
   [okulary.core :as l]
   [potok.v2.core :as ptk]
   [rumext.v2 :as mf]))

(def menu-ref
  (l/derived :context-menu refs/workspace-local))

(defn- prevent-default
  [event]
  (dom/prevent-default event)
  (dom/stop-propagation event))

(mf/defc menu-entry*
  {::mf/props :obj
   ::mf/private true}
  [{:keys [title shortcut on-click on-pointer-enter on-pointer-leave
           on-unmount children is-selected icon disabled value]}]
  (let [submenu-ref (mf/use-ref nil)
        hovering?   (mf/use-ref false)

        on-click'
        (mf/use-fn
         (mf/deps on-click)
         (fn [event]
           (st/emit! dw/hide-context-menu)
           (when on-click (on-click event))))

        on-pointer-enter
        (mf/use-fn
         (fn []
           (mf/set-ref-val! hovering? true)
           (let [submenu-node (mf/ref-val submenu-ref)]
             (when (some? submenu-node)
               (dom/set-css-property! submenu-node "display" "block")))
           (when on-pointer-enter (on-pointer-enter))))

        on-pointer-leave
        (mf/use-fn
         (fn []
           (mf/set-ref-val! hovering? false)
           (let [submenu-node (mf/ref-val submenu-ref)]
             (when (some? submenu-node)
               (timers/schedule
                200
                #(when-not (mf/ref-val hovering?)
                   (dom/set-css-property! submenu-node "display" "none")))))
           (when on-pointer-leave (on-pointer-leave))))

        set-dom-node
        (mf/use-fn
         (fn [dom]