Fork me on GitHub
#reagent
<
2021-11-30
>
Ryan15:11:40

Ok today I have a doozy.. trying to track down a deref in a lazy sequence in a sort of complicated bit of code.. I've tried my best to extract it into 1 blob:

Ryan15:11:09

Let me try and get this formatted better

Ryan15:11:08

I think I may need to deref the value object in test-questionnaire-panel.. and pass it in to get-questionnaire .. but I've tried a bunch of other things first and none worked so wasn't sure if that was the right idea

p-himik15:11:34

It's very hard to help you with this, for a few reasons: • Unclear what you want in the first place • There's a lot of domain-specific code • The code mixes Reagent and re-frame in non-obvious ways • Unclear whether it contains all the relevant details given that the code of pnx-web.events.core is not present

Ryan15:11:01

Yeah, I'm trying but this one is very hard to isolate

Ryan15:11:56

alright, what I want is to hand a component a map vector that describes a form and have that component generate that form.. this vector includes a function to determine if a particular element should display.

p-himik15:11:53

To make sure that you're not reinventing the wheel needlessly - have you seen available libraries for forms that work with Reagent or re-frame?

Ryan15:11:44

I saw fork and a few others, none seemed to provide all the functionality we need and also utilize the component library we are using for appropriate controls

Ryan15:11:54

So I looked at Fork and a couple others I can't name off top of head

Ryan15:11:44

It's all working as intended in testing, but its generating warnings:

Reactive deref not supported in lazy seq, it should be wrapped in doall

Ryan15:11:23

I think I can cut another big chunk out, now that you mention it.. the event code isn't really relevant to this problem and is working just fine.. that was the ref to the events.. the events are firing correctly.

Ryan16:11:13

Ok I chopped a ton more of it out

p-himik16:11:12

You're using @ on line 27, within for. And for creates a lazy sequence.

p-himik16:11:35

I'm 80% certain that that specific location is mentioned in the warning's stacktrace.

Ryan16:11:54

There is no reference to the file name or line number that I can spot in the stack trace

Ryan16:11:01

but now that you've clued me in, I do see it somewhat:

Ryan16:11:32

Warning: Reactive deref not supported in lazy seq, it should be wrapped in doall: ([:label {:class ":recommend radio-option selected"} [:input {:on-change #object[Function], :type "radio", :name :recommend, :checked "checked", :value "0"}] [:span "Not at all"]] [:label {:class ":recommend radio-option "} [:input {:on-change #object[Function], :type "radio", :name :recommend, :checked nil, :value "1"}] [:span "Maybe"]] [:label {:class ":recommend radio-option "} [:input {:on-change #object[Function], :type "radio", :name :recommend, :checked nil, :value "2"}] [:span "Definitely"]])
 (in pnx_web.views.questionnaire_test.question_radio) 
that last line.. I was looking down the stack trace looking for a filename

p-himik16:11:53

If you expand the warning in the JS console, does it not show the full stacktrace? If it doesn't, you can always find where such a warning is emitted in the Reagent's code within your browser and simply put a breakpoint there.

Ryan16:11:49

Yes, this is the stacktrace I get:

react_devtools_backend.js:2540 Warning: Reactive deref not supported in lazy seq, it should be wrapped in doall: ([:label {:class ":google radio-option "} [:input {:on-change #object[Function], :type "radio", :name :google, :checked nil, :value "0"}] [:span "Not at all"]] [:label {:class ":google radio-option "} [:input {:on-change #object[Function], :type "radio", :name :google, :checked nil, :value "1"}] [:span "Maybe"]] [:label {:class ":google radio-option selected"} [:input {:on-change #object[Function], :type "radio", :name :google, :checked "checked", :value "2"}] [:span "Definitely"]])
 (in pnx_web.views.questionnaire_test.question_radio) 
    at cmp ()
    at div
    at div
    at cmp ()
    at cmp ()
    at div
    at div
    at div
    at cmp ()
overrideMethod @ react_devtools_backend.js:2540
reagent$impl$template$expand_seq_check @ template.cljs:250
reagent$impl$template$as_element @ template.cljs:296
eval @ template.cljs:315
reagent$impl$protocols$as_element @ protocols.cljs:6
reagent$impl$template$make_element @ template.cljs:135
eval @ template.cljs:317
reagent$impl$protocols$make_element @ protocols.cljs:7
reagent$impl$template$native_element @ template.cljs:226
reagent$impl$template$hiccup_element @ template.cljs:261
reagent$impl$template$vec_to_elem @ template.cljs:285
reagent$impl$template$as_element @ template.cljs:294
eval @ template.cljs:315
reagent$impl$protocols$as_element @ protocols.cljs:6
eval @ template.cljs:140
eval @ core.cljs:5688
eval @ core.cljs:5688
eval @ core.cljs:5692
cljs$core$_kv_reduce @ core.cljs:715
cljs$core$reduce_kv @ core.cljs:2595
reagent$impl$template$make_element @ template.cljs:138
eval @ template.cljs:317
reagent$impl$protocols$make_element @ protocols.cljs:7
reagent$impl$template$fragment_element @ template.cljs:191
reagent$impl$template$vec_to_elem @ template.cljs:282
reagent$impl$template$as_element @ template.cljs:294
eval @ template.cljs:315
reagent$impl$protocols$as_element @ protocols.cljs:6
reagent$impl$component$wrap_render @ component.cljs:93
reagent$impl$component$do_render @ component.cljs:117
eval @ component.cljs:50
reagent$ratom$in_context @ ratom.cljs:44
reagent$ratom$deref_capture @ ratom.cljs:57
eval @ ratom.cljs:430
day8$reagent$impl$component$wrap_funs_$_render @ component.cljs:52
finishClassComponent @ react-dom.development.js:17486
updateClassComponent @ react-dom.development.js:17436
beginWork @ react-dom.development.js:19074
beginWork$1 @ react-dom.development.js:23941
performUnitOfWork @ react-dom.development.js:22777
workLoopSync @ react-dom.development.js:22708
renderRootSync @ react-dom.development.js:22671
performSyncWorkOnRoot @ react-dom.development.js:22294
eval @ react-dom.development.js:11328
exports.unstable_runWithPriority @ scheduler.development.js:469
runWithPriority$1 @ react-dom.development.js:11277
flushSyncCallbackQueueImpl @ react-dom.development.js:11323
flushSyncCallbackQueue @ react-dom.development.js:11310
scheduleUpdateOnFiber @ react-dom.development.js:21894
enqueueForceUpdate @ react-dom.development.js:12505
Component.forceUpdate @ react.development.js:385
reagent$impl$batching$run_queue @ batching.cljs:39
eval @ batching.cljs:88
eval @ batching.cljs:98
eval @ batching.cljs:78
G__52103 @ batching.cljs:59
G__53362 @ batching.cljs:17
requestAnimationFrame (async)
day8$reagent$impl$batching$next_tick @ batching.cljs:13
eval @ batching.cljs:59
reagent$impl$batching$enqueue @ batching.cljs:52
eval @ batching.cljs:74
reagent$impl$batching$do_after_render @ batching.cljs:121
reagent$impl$input$input_handle_change @ input.cljs:83
eval @ input.cljs:122
callCallback @ react-dom.development.js:3946
invokeGuardedCallbackImpl @ react-dom.development.js:3995
invokeGuardedCallback @ react-dom.development.js:4057
invokeGuardedCallbackAndCatchFirstError @ react-dom.development.js:4071
executeDispatch @ react-dom.development.js:8244
processDispatchQueue @ react-dom.development.js:8276
eval @ react-dom.development.js:8300
eval @ react-dom.development.js:22397
batchedEventUpdates @ react-dom.development.js:3746
dispatchEventForPluginEventSystem @ react-dom.development.js:8508
attemptToDispatchEvent @ react-dom.development.js:6006
dispatchEvent @ react-dom.development.js:5925
exports.unstable_runWithPriority @ scheduler.development.js:469
runWithPriority$1 @ react-dom.development.js:11277
Internals.Events @ react-dom.development.js:22414
dispatchDiscreteEvent @ react-dom.development.js:3757

Ryan16:11:18

sorry for wall of text, wondering if there's something wrong with my environment or something obvious I'm completely missing

p-himik16:11:54

Ah, alright, so I was wrong about the particular line being mentioned.

Ryan16:11:23

Just making sure, you usually aren't! 😄

Daniel Craig20:11:42

I have a form-3 component that doesn't update when my ratom changes - am I missing anything obvious? Code snippet in thread:

Daniel Craig20:11:51

(defn force-viz []
  (let [width 300
        height 300
        svg (create-svg width height)
        graph (re-frame/subscribe [:browse/graph])
        links (-> svg
                  (.append "g")
                  (.attr "class" "link")
                  (.selectAll "line")
                  (.data (.-links @graph))
                  (.enter)
                  (.append "line")
                  (.attr "stroke-width" (fn [d] (Math/sqrt (.-value d)))))
        nodes (-> svg
                  (.append "g")
                  (.attr "class" "node")
                  (.selectAll "circle")
                  (.data (.-nodes @graph))
                  (.enter)
                  (.append "circle")
                  (.attr "r" 5)
                  (.call (-> (.drag js/d3)
                             (.on "start" dragstart)
                             (.on "drag" dragged)))
                  (.on "click" click))]
    (re-frame/dispatch-sync [::events/set-simulation (simulation height width @graph links nodes)])
    (reagent.core/create-class
     {:display-name "force-viz"
      :component-did-mount (fn [this _]
                             (let [force-viz-node (-> js/document (.getElementById "force-viz"))]
                               (-> force-viz-node (.append (.node svg)))))
      :reagent-render (fn [] [:div [:object#force-viz]])})))

Daniel Craig20:11:37

the :browse/graph subscription is getting disposed and then the view never updates.

p-himik21:11:59

Nothing in the top-level let will be re-evaluated when graph changes - even if it depends on its value. You have to implement all the custom update logic in :component-did-mount

Daniel Craig21:11:30

Ohh ok thanks!

Daniel Craig22:12:55

I'm finding that if I move the bindings of links and nodes inside the let form inside of component-did-mount, the subscription still doesn't re-run when I expect it to. Could you reset my expectations once again?

(defn force-viz []
  (let [width 300
        height 300
        svg (create-svg width height)
        graph (re-frame/subscribe [:browse/graph])
        ]

    (reagent.core/create-class
     {:display-name "force-viz"
      :component-did-mount (fn [this _]
                             (let [links (-> svg
                                             (.append "g")
                                             (.attr "class" "link")
                                             (.selectAll "line")
                                             (.data (.-links @graph))
                                             (.enter)
                                             (.append "line")
                                             (.attr "stroke-width" (fn [d] (Math/sqrt (.-value d)))))
                                   nodes (-> svg
                                             (.append "g")
                                             (.attr "class" "node")
                                             (.selectAll "circle")
                                             (.data (.-nodes @graph))
                                             (.enter)
                                             (.append "circle")
                                             (.attr "r" 5)
                                             (.call (-> (.drag js/d3)
                                                        (.on "start" dragstart)
                                                        (.on "drag" dragged)))
                                             (.on "click" click))
                                   force-viz-node (-> js/document (.getElementById "force-viz"))]
                               (re-frame/dispatch-sync [::events/set-simulation (simulation height width @graph links nodes)])
                               (-> force-viz-node (.append (.node svg)))))
      :reagent-render (fn [] [:div [:object#force-viz]])})))

p-himik02:12:51

Oh shoot, sorry - I wrote garbage above. You have to set things up in :component-did-mount and implement update logic (which may or may not be the same where you set things up) in :component-did-update.