day8 / re-frame-10x

A debugging dashboard for re-frame. X-ray vision as tooling.
MIT License
636 stars 68 forks source link

[Bug]: Panel does not update when dereferencing a React ref in reagent atom #380

Closed JordanSkousen closed 1 year ago

JordanSkousen commented 1 year ago

What happened?

When dereferencing a React ref stored in a reagent.core/atom, the re-frame-10x panel stops updating - no events are displayed and the app-db does not update. It is still interactable, so it is not completely frozen. Interestingly, when switching tabs and coming back the panel updates upon switching, but continues to not update.

Here's some sample code of a demoing this out. The h1 uses reagent's ref feature, and toggling the checkbox will turn off/on dereferencing the ref to the h1, which will toggle off/on breaking the 10x panel.

(ns app.core
  (:require [reagent.dom :as rdom]
            [reagent.core :as r]
            [re-frame.core :refer [subscribe dispatch reg-event-db reg-sub]]))

(defn view []
  (let [ref (r/atom nil)]
    (fn []
      (let [break-mode-on? @(subscribe [:break-mode-on?])]
        [:<>
         [:h1 {:ref #(reset! ref %)}
          "This h1 is used as an example ref"]
         [:input {:type "checkbox"
                  :id "breaker"
                  :value break-mode-on?
                  :on-change #(dispatch [:break-mode-on? (.. % -target -checked)])}]
         [:label {:for "breaker"}
          "Click here to break re-frame-10x panel"]
         (when break-mode-on?
           [:div "De-refed ref: " (str @ref)])
         [:br]
         [:span "This input is controlled by re-frame db:"]
         [:input {:value @(subscribe [:test-input-val])
                  :on-change #(dispatch [:test-input-val (.. % -target -value)])}]]))))

(reg-event-db
 :test-input-val
 (fn [db [_ val]]
   (assoc-in db [:test-input-val] val)))

(reg-event-db
 :break-mode-on?
 (fn [db [_ on?]]
   (assoc-in db [:break-mode-on?] on?)))

(reg-sub
 :test-input-val
 (fn [db _]
   (get-in db [:test-input-val])))

(reg-sub
 :break-mode-on?
 (fn [db _]
   (get-in db [:break-mode-on?])))

(defn ^:dev/after-load mount-root []
  (rdom/render [view] (.getElementById js/document "app")))

(defn ^:export main []
  (mount-root))

10x Version

1.5.0

Reagent Version

1.1.1

React Version

18.2.0

re-frame Version

1.3.0

What browsers are you seeing the problem on?

Firefox, Chrome, Microsoft Edge

Relevant console output

No response

JordanSkousen commented 1 year ago

Sorry. I didn't read the Using Refs documentation closely enough.

We use a normal Clojure atom because refs never change during the lifecycle of a component and if we used a reagent atom, it would cause an unnecessary re-render when the ref callback mutates the atom.

All I need to do is change from a reagent.core/atom to a clojure.core/atom and it's working.