Fork me on GitHub
#re-frame
<
2016-09-19
>
borkdude08:09:07

Is there in re-frame something like: I have events x and y but they must also trigger event z? like for example, I want to dismiss an error message when someone hits a button, touches the menu, etc

mikethompson08:09:53

@borkdude might be a good case for an reusable interceptor

mikethompson08:09:14

Each event which should trigger a further z can be wrapped in that interceptor

mikethompson08:09:14

so the event handlers for x and y would have this interceptor (which dispatches a z)

mikethompson08:09:53

(def  dispatch-z 
  (->interceptor 
     :id     :trigger-z
     :after  (fn [context]  
                  (update-in context [:effects :dispatch-n]  conj [:z]))))
Note: 1. We are conj-ing to the :dispatch-n effect (which is standard)

mikethompson08:09:14

And then we add this interceptor to the event handlers for x and y

(reg-event-db 
    :x
    [ dispatch-z  .... ]      ;; <----  interceptor added here
    (fn [db event] 
       .....))

reefersleep08:09:28

*reg-event-db

reefersleep08:09:51

🙂 And just for completeness (though I suspect @mikethompson's example makes more sense in this case), you could dispatch z within a reg-event-fx rather than a reg-event-db if you only want to do it a couple of places and don't care about the neat reuseability of a vector (EDIT: interceptor), as explained in Step 1 Of Plan here: https://github.com/Day8/re-frame/blob/master/docs/EffectfulHandlers.md @borkdude

mikethompson08:09:12

Indeed. So if you didn't want a reusable interceptor, you can manually return the dispatch effect:

(reg-event-fx              ;; now using -fx  
   :x                      ;; no longer has an interceptor, we're doing it manually below
   (fn [{db :db}  event]   ;; first parameter is now the coeffects, not just db
     {:db        (assoc db :do :something)
      :dispatch  [:z]}))       ;; here we go ... dispatch that :z event

mikethompson08:09:43

Note: there are a few standard effects :dispatch :dispatch-n :dispatch-later and, soon, :dispatch-debounce

mikethompson08:09:51

Directly above I'm using :dispatch for simplicity, but in the interceptor further above I used :dispatch-n because I can always safely conj onto that, no matter what the event handler returns

yury.solovyov09:09:06

in general is it better to have flat app-db structure or with nested maps?

yury.solovyov09:09:35

with flat structure key names become long

borkdude10:09:54

sorry, I was away, but will read your responses now 🙂

borkdude10:09:50

I like the reg-event-fx approach

reefersleep10:09:52

@yury.solovyov: Since re-frame abstracts away the db handling fns from your components, I find that since you no longer have a need for the db shape to match the components, you can do whatever you find most comfortable. I prefer nested maps for the same reason you do. Also, nested maps makes much more sense in our team's state viewer component, where they can be folded in and out at will 🙂 So we can zoom in on the pertinent area.

yury.solovyov10:09:07

I was just following python zen "Flat is better than nested"

yury.solovyov10:09:22

maybe blindly though

reefersleep10:09:15

In many cases, that surely applies.

borkdude12:09:39

Is there anything against writing:

(reg-event-db :x
    (fn [db _]
      (dispatch [:z])
      (assoc db …)

borkdude12:09:18

instead of using reg-event-fx

borkdude12:09:51

what if you need to dispatch multiple events in reg-event-fx

yury.solovyov12:09:57

I think this is done via vector

yury.solovyov12:09:06

dispatch [:do-something-else 3]

borkdude12:09:11

that is only one event

yury.solovyov12:09:45

will dispatch [:do-something-else 3 :and-more 42] work?

yury.solovyov12:09:34

me too, just guessing

dev-hartmann15:09:12

Hey fellow clojurians, i have a question. I have a subscription on a list of item and when i build the List, i have two input fields to create a tag for the list entry. If i create an Event will be sent to the backend and add a tag to the entry. Problem is, the frontend will not rerender obviously, because nothing on the list subscription changed. Any ideal how to Update the changed entry in the List, in Order Not to reload the whole list?

shaun-mahood15:09:39

@dev-hartmann: Welcome! Are you able to share the code that's giving you problems? In general, you will have to have something that is able to see that there has been a change in order to update, so either a new subscription, an additional change that your event makes, a new event, or something else along those lines.

yury.solovyov19:09:30

is there a way to perform more that one update to db for :db effect?

yury.solovyov19:09:30

like :db (assoc db :foo 42) (assoc db :bar 1)

yury.solovyov19:09:22

maybe via merge somehow?

shaun-mahood19:09:17

@yury.solovyov: You should be able to use the thread-first macro (https://clojuredocs.org/clojure.core/-%3E) and do

:db (-> db 
    (assoc :foo 42)
    (assoc :bar 1))

yury.solovyov19:09:37

yeah, look nicer than (assoc db panel (merge (panel db) {:updating true :current-path new-path}))

shaun-mahood19:09:52

That's a pattern I used a ton in pre-0.8.0 but I haven't tested it yet that exact way, so let me know if it doesn't work.

yury.solovyov19:09:42

yup, works, thanks

snoe20:09:34

@yury.solovyov you can use update there: (update db :panel merge {:updating true :current-path new-path})

yury.solovyov20:09:02

@snoe thanks, yeah, that's an option too

johanatan23:09:35

Hi, I have a layout change (i.e., new DOM elements inserted shifting existing ones down) triggered by some atom's data changing (suppose a new section added to a page). I also have mouseenter and mouseleave event handlers setup on individual elements. If said layout change results in a change to which element is underlying the current mouse pointer, then my effects in the mouse handlers (which do typical "highlight color" stuff) do not run for the new element under the cursor (or for the old element under the previous relative cursor position for that matter).

johanatan23:09:46

Anyone encountered similar problems or have any ideas for solutions?

jvuillermet23:09:55

If you "leave" the element and "enter" again it would work right ?

johanatan23:09:37

Yes, that would work

johanatan23:09:16

But then I'd have an awful lot of stateful stuff going on: i.e., querying the system for the location of the mouse pointer (only under this particular type of re-render) and then triggering events manually

johanatan23:09:41

[i've added an :on-mouse-over and that mostly handles it: but i still need the mouse to move one pixel to really get back up to date]

johanatan23:09:12

[i.e., without :on-mouse-over, the mouse/user has to exit the panel completely and then go back into it (or another panel)]

jvuillermet23:09:53

ok I understand

johanatan23:09:15

Hmm, actually i guess i could just query the system for the element under the cursor and allow that to override my atom's storing the values for whether an element is hovered or not (at the start of the render cycle)

jvuillermet23:09:17

and playing with keys so it's not rendered again could help ?

johanatan23:09:00

well, if the mouse moved out of the element as a result of the new insertions, it would need to be rendered again

johanatan23:09:18

[or vice versa, if into an element it weren't in previously]

johanatan23:09:41

and i doubt that react + :keys would consider mouse position when determining if it should re-render

johanatan23:09:33

this just seems like such a common scenario that i figured that others would've come up with some standard solution (as it would be a problem for any React app-- not just reframe/reagent)

jvuillermet23:09:49

never encountered this but thats interesting

johanatan23:09:08

i guess for now i'm ok with the "one pixel move" requirement (as we are in MVP stage only at this point 🙂 )

johanatan23:09:19

but yes would be great to find a real solution

jvuillermet23:09:09

I dont have any other idea right now, let's wait for other people to read

johanatan23:09:25

normally i'd try to use CSS for this but it was being very finicky hence my resorting to manual on-mouse-enter and on-mouse-leave

jvuillermet23:09:41

Do you have the same pb with css ?

johanatan23:09:44

no, different problem. couldn't even get it to work at all (even without the re-layout complexity)

johanatan23:09:52

although i do have other parts of the app where it works

johanatan23:09:15

i think it had to do with wanting to change descendant properties from ancestor's :hover

johanatan23:09:36

[although that should be possible-- it's complicated. there was one other complicating factor i forget at the moment]

johanatan23:09:48

oh, it was that background is not an eligible property for that kind of change

johanatan23:09:54

[and i'm using background images here]

johanatan23:09:13

sorry, that may not all be exact: but it was definitely some combination of two factors along similar lines like that

nikp23:09:10

Thought some of you might find this useful. It's a collection of utility/syntactic sugar functions for re-frame I find myself using in a lot of re-frame projects https://github.com/nikolap/reframe-utils