Fork me on GitHub
#fulcro
<
2020-08-12
>
alex-eberts14:08:05

Hi all - is there a fulcro study group planned for today at 4pm BST?

zilti16:08:55

Okay now I am really scratching my head over here... How do I trigger a root re-render? And why does an m/set-value! inside a :onMouseEnter event not trigger a component re-render?

tony.kay16:08:36

@zilti refresh of component will only happen if props change. Is the thing you’re doing set-value on in the query? Does the component have an ident? To your question: schedule-render! can be used to schedule a new render, but it depends on what renderer you have installed as to what that does. There is a force-root option. See app ns.

tony.kay16:08:58

as far as events go: see React docs. Fulcro has nothing to do with that

zilti16:08:09

Yes, it has an ident, and yes, the m/set-value! targets something in the query

tony.kay16:08:30

Then it should update

tony.kay16:08:45

(assuming the value changed)

tony.kay16:08:06

call signature correct? You’re not using :event or something are you?

zilti16:08:08

According to Fulcro Inspect, it changed indeed

tony.kay16:08:11

set-value doesn’t support that

zilti16:08:25

No, it is (m/set-value! this :ui/mouseover? true)

tony.kay16:08:39

check your logic

tony.kay16:08:52

perhaps you’ve got nesting of an if screwed up or something

tony.kay16:08:02

or a weird cond

tony.kay16:08:24

run a log stmt on the value of props as first stmt of body…if that prints, you’re definitely re-rendering

zilti16:08:56

I tried that, it doesn't print

tony.kay16:08:21

did you mess with shouldComponentUpdate?

zilti16:08:41

No, it is a bog-standard component

tony.kay16:08:41

is the prop spelled correctly in the query?

tony.kay16:08:11

If you use onClick does it work?

zilti16:08:13

Hmm. I am using this element like normal, I created a (comp/factory SidebarItem {:keyfn :ui/text}) for it and use it using (ui-sidebar-item {:ui/text "TestItem" :ui/target TargetElement})

zilti17:08:43

Also, (app/schedule-render! (comp/any->app this) {:force-root? true}) does not actually render the entire tree for at least a multiple-roots-renderer.

tony.kay17:08:21

how is it supposed to get changing props if you don’t pass them in?????

zilti08:08:33

If I pass in :ui/mouseover? it just gets ignored. It never shows up in the normalized database. I guess I'm going to use local state then

tony.kay14:08:20

You’re clearly doing something very strange that is counter to the design. Writing a query and then passing a literal map has nothing to do with Fulcro, period.

tony.kay17:08:57

and I do not think you are correct…though root’s shouldComponentUpdate almost certainly short-circuits it all if no props have changed

tony.kay17:08:52

mrr is a render from root renderer + render alt registered roots

tony.kay17:08:13

force-root-render! will cause SCU to be ignored

tony.kay17:08:53

or you can add an SCU true to your root..which I commonly recommend (the props check in SCU at root is mostly a waste of time, since most renders are due to a change of something in the app)

tvaughan17:08:36

In a defsc component, how should I do something like (js/setTimeout #(set! (.-transition (.-style **this**)) "fade") 2500) ? How do I get the necessary javascript object from this which is a fulcro component? Or should I take a different approach?

tvaughan19:08:06

Do you mean like this? https://github.com/reagent-project/reagent/blob/master/doc/FAQ/UsingRefs.md Use an atom to store the javascript object, set the atom somehow using :ref, and then dereference the atom to set the timeout?

lgessler19:08:14

yup, i'm pretty sure reagent and fulcro are both using the same react machinery under the hood

lgessler19:08:27

the example in the fulcro book i linked above should give you the idea

tvaughan19:08:02

I don't understand the example in the fulcro book, but I think I understand the concept. Thanks!

lgessler19:08:38

basically what's happening is that the component's local state is initialized with a function that saves a reference to the real dom element you're interested in, then in your markup you feed that function to its :ref prop, so that when the component is mounted the ref saving function is fired and this now has a ref to the dom element

lgessler19:08:56

which you can then use to do whatever you like with it either in componentDidMount or in response to some user action

lgessler19:08:58

I'm not sure if it's absolutely necessary to use gobj/set on this like the example in the fulcro book does... i feel like using component local state would be fine too

tvaughan19:08:01

Yeah, I was hoping for something simpler. This is all I need to do:

(defsc Toast
  [this {:keys [toast/status toast/short toast/message] :as props}]
  {:query [:toast/status :toast/short :toast/message]
   :ident (fn [] [:component/id :toast])}
  (js/setTimeout #(set! (.-transition (.-style this)) "fade") 2500)
  (dom/div :.ui.floating.message
           {:classes [(name status)]}
           (dom/div :.header
                    short)
           (dom/p message)))
I just need to get the right this to set the timeout

lgessler19:08:55

separately, i'm a little afraid of whether having the timeout in the rendering function is OK... might it be enough to put it in componentDidUpdate?

lgessler19:08:41

(defsc Toast
  [this {:keys [toast/status toast/short toast/message] :as props}]
  {:query [:toast/status :toast/short :toast/message]
   :ident (fn [] [:component/id :toast])
   :initLocalState (fn [this _]
                     {:save-ref (fn [r] (gobj/set this "message-element" r))})
   :componentDidUpdate (fn [this _ _]
                         (js/setTimeout #(set! (.-transition (.-style (gobj/get this "message-element"))) "fade") 2500))}
  
  (let [save-ref (comp/get-state this :save-ref)]
    (dom/div :.ui.floating.message
             {:classes [(name status)]
              :ref save-ref}
             (dom/div :.header
                      short)
             (dom/p message))))

lgessler19:08:44

i think you want something like this

2
tvaughan20:08:24

Cool, thanks! componentDidUpdate is never triggered. componentDidMount is triggered (I understand this may not be the correct method) and I do see that the transition is being added by the timeout callback