Fork me on GitHub
#re-frame
<
2017-10-27
>
jumar07:10:05

how is re-frame-trace different from re-frisk, perhaps combined with debug interceptor? Is there a rationale to use both of them?

lovuikeng07:10:26

I suppose it's easy be explained by http://www.daiyi.co/dev-diary/2017/10/19/re-frame-trace/ Re-frisk is useful as event log and tracing

borkdude09:10:42

@mikethompson I’d love to hear your feedback on this answer, since it seems a bit complex to me… https://stackoverflow.com/a/46904084/6264

mikethompson09:10:04

@jumar bottomline, they are similar currently. re-frame-trace gives a bit more information which might be useful in some cases. But re-frisk has abilities like "pop out window" which is great. Some many prefer the presentation of app-db in one over the other. We've been active users of re-frisk and we like it a lot. Until recently re-frame-trace was not nearly as good as re-frisk, although recently it has taken some good steps forward. Four years ago we tried to develop a debugger called Abra, but somehow that never worked out. So then we pivoted to use clairvoyant, improved it, and documented it's use, but it too had some limitations. re-frame-trace is something we started about a year ago, and we've been working on since, when we have the time (there hasn't been a lot). Saskia and Daiyi from the The Ruby Girls Summer Of Code project recently gave it a really nice kickalong. Our eventual goal is that re-frame-trace acts as "a developer dashboard" or something. Still a work in progress. Recent improvements, more to come. Not sure where we'll end up.

selim12:10:16

Hi there! I want to create a effect handler with the basic job of transforming the data passed to it and delegate to :http-xhrio What is the best strategy for it? The use case in mind is to have a graphql handler which will accept the query parameters, form the query and pass it to :http-xhrio

danielneal12:10:14

Hi funnily enough I do exactly that

danielneal12:10:23

I do it with an interceptor though

danielneal12:10:16

this probably doesn't do what you want exactly

danielneal12:10:25

and a bit more around handling certain errors

danielneal12:10:38

and authorization states

danielneal12:10:57

and I'm not using http-xhrio because I'm on react native so I've got a different http effect hanlder

selim12:10:57

I see, but that’s a great example. Thanks a lot. And interceptor is a good pointer too. I didn’t think of that feature.

danielneal12:10:22

yeah, I started off trying to make an effect, but then realised I wanted to transform the data, rather than do a side effect

danielneal12:10:34

you could also have a graphql event though

danielneal12:10:43

that might be easier 😂

danielneal12:10:00

(reg-event-fx [:graphql/query q] ... {:http-xhrio ...})

selim12:10:35

Even better 🙂

selim12:10:12

The downside is I prefer the events to represent domain events but it’s a reasonable trade off I guess

danielneal12:10:52

yeah, I've ended up with a bit of a convention where I have :ui.search/set-query for a user interface generated event, and things like :data.search/search and :navigation/set-route for internally generated events that might be dispatched based on the ui event

danielneal12:10:59

not sure what other people do, would be interested to know

selim13:10:07

hmm how about this: (dispatch [:domain-event}) -> (reg-event-fx [:domain-event] ... {:graphql..} -> (reg-fx [:graphql..] (dispatch [:graphql/query ...]) -> (reg-event-fx [:graphql/query ...] ... {:http-xhrio ..]}

danielneal13:10:17

yeah that would do it too

selim13:10:36

basically domain events produce a :graphql effect whose handler is generic and dispatch a :graphql/query that would decouple things I guess

danielneal13:10:36

I guess it's a matter of taste

selim13:10:34

Yep. Thanks for the thought exercise 🙂

lumpy13:10:20

Does anyone have a good example of the right way to do lists. Have been creating subscriptions that return a collection of list items then iterating through them in the view. Now thinking that logic should live in a subscription and create a list item sub that uses the index to fetch the correct info for that item. How are people doing lists?

reefersleep14:10:50

Hello lumpy 🙂 I’m very much a fan of having the read and update logic in subscriptions and actions, and the view being very dumb.

reefersleep14:10:20

I’m very happy with the most recent iteration in my hobby project, which is to have a map with keys being ids, and vals being the list-item data. E.g.

{4321 {:id 4321, :name “Jack”, :age 16}
 1234 {:id 1234, :name “Joe”, :age 20}}

reefersleep14:10:57

The id duplication is just for convenience, since I need it in my action handling fns.

reefersleep14:10:09

Oh, and I use a map rather than a list, since updating sort order in a map is easier (imo) than updating stuff nested in a vector.

reefersleep14:10:22

I have :sort-order as a key in my item maps as well.

lumpy14:10:39

So then the list-item view just uses the id to render?

reefersleep14:10:55

Lemme link you up

reefersleep14:10:01

I’m sorry about the general state of the code

reefersleep14:10:11

but I l like my list logic

reefersleep14:10:30

I’m at work now, but I can illustrate what I mean when I get home with some pointers and examples

reefersleep14:10:21

I don’t use re-frame at work (not my choice), but I do work with Clojure and Clojurescript every day, just to say that I’m not just a hobbyist 🙂

lumpy16:10:35

thanks, this was helpful to look at 🙂

reefersleep18:10:24

Ah, you’re OK then? 🙂

reefersleep18:10:37

jus sat down at my home computer :robot_face:

reefersleep13:10:22

I don’t think that there’s anything glorious about my code or ideas, but maybe the ones re: lists in reagent would make for a good blog entry. Seems like there’s always enough people interested in the nitty-gritty details of stuff like this, since it’s not a given from reagent or re-frame that you do lists in a certain way. What do you think?

lumpy17:10:44

I would read it for sure

reefersleep10:10:39

😄 I'll consider it. Hope your project is faring well!

mf14:10:56

Hi, hoping someone can advise on what the best way to achieve the following functionality is: I have two components (`component-a` and component-b). * component-a renders component-b supplying a default-msg and optional error-msg argument. * component-b should render the default-msg unless an error-msg argument is supplied. * If an error-msg is supplied then component-b should also render a hide-error button. * When the hide-error button is clicked component-b should be re-rendered showing just the default-msg. This works the first time component-a renders component-b with an error-msg:

(defn component-b [default-msg & options]
  (let [show-error (atom true)]
    (fn [default-msg & {:keys [error-msg]}]
      (if (and @show-error error-msg)
        [:span
         (str "showing error message: " error-msg)
         [:button.close {:on-click #(reset! show-error false)} "hide error"]]

        [:span
         (str "showing default message: " default-msg)]))))

(defn component-a []
  (let [error (subscribe [::subs/my-error])]
    [component-b
     "hello world"
     :error-msg @error]))
The problem is that if a user clicks hide-error then subsequent component-b re-renders (triggered when component-a's subscription changes) will always render the default-msg (this is expected as component-b's show-error state persists across renders). Can anyone advise how best to achieve my desired functionality? Thanks

stvnmllr216:10:06

Hey all, I was keeping a list of contacts in the "db" client side. Then someone imported 2700 contacts. And everything that accessed any part of the "db" got slow. I'm guessing that's expected right? Not something I can avoid?

danielneal16:10:55

the thing to avoid is re-evaluating subscriptions when you don't need to

danielneal16:10:14

if you have subscriptions that depend just on db, then whenever the db changes, all the subscriptions will update - which is what you're seeing

danielneal16:10:14

if you have what @mikethompson calls layer 1 and layer 2 subscriptions, where layer 1 are simple gets to a bit of the db, then you can avoid the recalculation problem, so at least it will only be slow when you actually need to recompute a subscription

mf16:10:48

:thumbsup: @danieleneal good advice. One thing (correct me if I'm wrong) but Subscription handlers that just take bits of app-db are referred to as Layer 2 subscriptions handlers and Subscription handlers dealing with derived data are Layer 3. I'm not sure I have seen reference to Layer 1 handlers....

lumpy16:10:28

is it really all subscriptions that are re-run or just ones that are in active components? If a sub isn’t subscribed to it won’t be ran right?

mf16:10:43

- So Layer 1 is the app-db, if I understand correctly?

stvnmllr216:10:44

ok, thanks for verifying that @danieleneal! Sort of what i thought, but didn't think i had any subscriptions like that, but I must. I'll start digging. Thanks again.

lovuikeng16:10:33

layer 2 (only value) and layer 4 (value with hiccup) are commonly used for subscriptions, layer 3 is computed materialized view

stvnmllr217:10:21

And to complete the circle, yes, i still had a subscription to the entire db from early days when I was playing with it. Removing it fixed it right up!

qqq19:10:59

rc here is reagent.core -- is there a simpler way to rewrite this?

;; app-div is an HTML dom element
;; gui-state is a reagent.core/atom
(let [render-func (fn [gui-state]
@gui-state)]
(rc/render [render-state gui-state] app-div))