Fork me on GitHub
#re-frame
<
2023-10-30
>
Tanner Hoelzel21:10:37

I'm wondering if reagent https://github.com/reagent-project/reagent/blob/master/doc/InteropWithReact.md#example-function-as-child-components can be used with re-frame. I'm working through an https://github.com/atlassian/react-beautiful-dnd/issues/427#issuecomment-420563943 from reagent and my code is as follows:

(defn main-panel []
  (let [items (re-frame/subscribe [::subs/items])
        selected-item (re-frame/subscribe [::subs/selected-item])
        panel-dnd-id "todo-list-dnd"]
    [:div
     ;; Uncommenting below forces the map-indexed list to stay updated
     ;; [:div "Items: " (str @items)]
     [:div
      [:p "Selected item: " @selected-item] 
      [item-input]
      [drag-drop-context
       {:onDragStart  (fn [result]
                        (re-frame/dispatch [:lift (get-in result [:source :index])]))
        :onDragUpdate (fn [result] (println result))
        :onDragEnd    (fn [result] (println result))}
       [droppable
        {:droppable-id panel-dnd-id :type "thing"}
        (fn [provided snapshot]
          (re-frame/as-element
           [:div (merge {:ref   (.-innerRef provided)
                         :class (when (.-isDraggingOver snapshot) :drag-over)}
                        (js->clj (.-droppableProps provided)))
            [:h2 "My List - render some draggables inside"
             (doall
              (map-indexed
               (fn [index item]
                 ^{:key (:id item)}
                 [:div.row
                  [draggable {:draggable-id (str (:id item)), :index index}
                   (fn [provided snapshot]
                     (reagent/as-element
                      [:div (merge {:ref (.-innerRef provided)}
                                   (js->clj (.-draggableProps provided))
                                   (js->clj (.-dragHandleProps provided)))
                       [:p (:val item)]]))]])
               @items))]
            (.-placeholder provided)]))]]]]))
My hunch is that I am misusing the re-frame subscription @items by keeping it in an anonymous function to be passed to the droppable component. Can anyone point me in the right direction?

p-himik21:10:47

Your comment in the code basically tells what's wrong. You need to deref items in the main-panel component itself. E.g. (let [items @items] ...) and use the actual value in the doall form.

Tanner Hoelzel21:10:22

I assume this is the best way? It seems like a kind of abuse of re-frame, am I wrong? Edit: Also thank you

p-himik21:10:02

Not an abuse at all, that's one of the valid ways to do it. Might be better if you turn the body of the function in map-indexed into its own component and subscribe and deref the value there (don't be afraid of subscribing multiple times to the same thing - the stuff's cached so it's rarely a problem).

Ben Lieberman21:10:38

Given a namespace containing various calls to reg-event-fx, reg-event-db, etc., loading that namespace should be sufficient to register those effect handlers, right? That has always been my understanding. But I'm splitting some modules and I must be missing something because my effect handlers are not being registered. The outputted JS shows that the namespace with my effect handlers is being imported.

p-himik21:10:33

> loading that namespace should be sufficient to register those effect handlers, right? That's correct. > The outputted JS shows that the namespace with my effect handlers is being imported. Either you're interpreting that JS wrong or you aren't loading that particular JS file. I can't think of any other non-convoluted reason for why else would the events not be registered.

Ben Lieberman21:10:32

I see this:

import "./cljs-runtime/nia.events.core.js";
SHADOW_ENV.setLoaded("nia.events.core.js");
which is the namespace in question. Is that not enough?

p-himik21:10:38

If you add (js/console.log "loaded") at the top level of that namespace, does it get printed in the JS console when you think the events are supposed to be registered?

Ben Lieberman21:10:08

that does print "loaded" but only after re-frame complains about the missing effect handler. I think it's to do with the way I'm starting up my application though. I'm dynamically importing a module but I suppose since that's gonna be returning a Promise that it's not blocking until the import is resolved?

p-himik21:10:44

Of course, promises don't block anything.

p-himik21:10:56

If you want eager loading, then don't use module splitting.

Ben Lieberman21:10:36

yeah, I think that's probably it then :face_in_clouds:

Ben Lieberman22:10:18

It was indeed, duh. thanks.

👍 1