Fork me on GitHub

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


I suppose it's easy be explained by Re-frisk is useful as event log and tracing


@mikethompson I’d love to hear your feedback on this answer, since it seems a bit complex to me…


@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.


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


Hi funnily enough I do exactly that


I do it with an interceptor though


this probably doesn't do what you want exactly


and a bit more around handling certain errors


and authorization states


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


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.


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


you could also have a graphql event though


that might be easier 😂


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


Even better 🙂


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


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


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


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 ..]}


yeah that would do it too


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


I guess it's a matter of taste


Yep. Thanks for the thought exercise 🙂


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?


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.


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}}


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


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.


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


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


Lemme link you up


I’m sorry about the general state of the code


but I l like my list logic


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


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 🙂


thanks, this was helpful to look at 🙂


Ah, you’re OK then? 🙂


jus sat down at my home computer :robot_face:


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?


I would read it for sure


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


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)
         (str "showing error message: " error-msg)
         [:button.close {:on-click #(reset! show-error false)} "hide error"]]

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

(defn component-a []
  (let [error (subscribe [::subs/my-error])]
     "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


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?


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


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


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


: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....


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?


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


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.


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


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!


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]
(rc/render [render-state gui-state] app-div))