re-frame

https://github.com/Day8/re-frame/blob/master/docs/README.md https://github.com/Day8/re-frame/blob/master/docs/External-Resources.md
whoops 2020-07-01T03:11:20.183700Z

I think I'm a bit confused... subscriptions can take an argument. I feel like you should be able to do

(rf/reg-sub
 ::get-tag
 (fn [db tag]
   (get db tag)))

(defn my-conponent []
  (let [data @(rf/subscribe [::get-tag :my-tag])]))

whoops 2020-07-01T03:14:22.184Z

That way you only have one sub, and even if tags are added dynamically, you can easily subscribe to new ones.

ruben.hamers 2020-07-01T03:31:58.184200Z

Yeah, It is set as Json in the json. When I set the :content-type to multipart/form-data it wont work.

ruben.hamers 2020-07-01T03:42:17.184400Z

when I try the same with Insomnia. Set the content type to multipart-form-data it wont work. ( when I test through the browser just running the swagger UI it does work)

ruben.hamers 2020-07-01T03:54:16.184600Z

ok, got it working in insomnia now

ruben.hamers 2020-07-01T04:26:56.184800Z

-----------------------------175945971223698693323893870064
Content-Disposition: form-data; name="file"; filename="test.txt"
Content-Type: text/plain

ajsdnasd 
-----------------------------175945971223698693323893870064--

ruben.hamers 2020-07-01T04:27:24.185Z

getting a 500 error file upload exception

ruben.hamers 2020-07-01T04:27:45.185200Z

getting closer:P

Oz 2020-07-01T07:50:04.185400Z

What I was looking for, but not what I needed

2020-07-01T07:58:30.185600Z

I thought that that you was using subscribe in the main body of reg-sub, which is not the way it was intended to be. As for Layer 3 subsription performance I think it depends. According to @mikethompson

And, to answer you question, layer 3 are not about less rendering (in general).  The propagation pruning layer is Layer 2.  Layer 3 is about performing the the expensive computation.

Setzer22 2020-07-01T08:48:17.189300Z

I am trying to do a fade-in animation with re-frame. I already have a fade-in-1s css class that works. The problem is that I have a form like this:

[:div.fade-in-1s
  [:h "Step description"]
  [:p "Step contents"]
  ...]
This is part of a panel that will show several "steps", and I want the fade-in animation to play at every step transition. However, I can only see my the fade-in animation when the first step is displayed. When I transition between steps, only the inner [:h] and [:p] are redrawn, but not the whole div (I assume this is re-frame being smart and diffing the HTML). How can I force the redraw of the whole div, so the fade-in animation is triggered?

2020-07-01T08:50:25.189700Z

Hi @setzer22, may be you can set a new key at each refresh

^{:key new-refresh-key-here}[:div.fade-in-1s ...

Setzer22 2020-07-01T08:52:18.189900Z

that works, thanks! 👍

1👍
2020-07-01T08:54:28.190100Z

Also remember that you can use libraries like Framer Motion here is an example of use https://github.com/reagent-project/reagent/tree/ce1dbe1be4534ca556fb05c4fede3fd6ac41b7cf/examples/framer-motion

1👍
2020-07-01T10:10:48.190500Z

So if you can't use subscribe in the main body of reg-sub, how can you achieve what I described in 2?

2020-07-01T10:41:30.192200Z

But what if I need to subscribe to a subscription, whose parameter depends on some other value I obtain from another subscription.

2020-07-01T10:42:00.192400Z

Say, in my case, a link has two endpoints and only need to depend on their positions and not on position of all units.

2020-07-01T10:42:41.192600Z

I could in principle obtain the ids of endpoints in my view and send them to another subscription, but that seems incorrect to me since subscription logic will be leaking into my views.

2020-07-01T10:43:50.192800Z

Using @(rf/subscribe [:node/pos endpoint-id]) works within the main body of my subscription. So my question is what is the downside of using it like this?

2020-07-01T11:21:15.193Z

p-himik 2020-07-01T12:09:50.193100Z

No downsides. As to your question about feeding sub value into another sub, you can just use reg-sub-raw for that.

p-himik 2020-07-01T12:10:23.193300Z

Ah, sorry, I missed the fact that you deref inside the body of a subscription and not a view. Here, I'm not sure.

2020-07-01T13:56:33.193600Z

So basically the correct way would be to use reg-sub-raw. I will take a look at it how it works precisely.

dpsutton 2020-07-01T14:09:07.194100Z

is there a preferred way to donate to re-frame? or perhaps just to an individual?

2👍
2020-07-01T14:25:59.194400Z

Not yet. I haven't ever set something up

2020-07-01T14:26:58.195200Z

Perhaps I should setup a Github sponsors ability

9👍
kelveden 2020-07-01T15:21:27.195300Z

In the end I actually wrapped up the defining of the two "chained" handlers into a separate function:

(rf/reg-fx
  :get-token
  (fn [{:keys [dispatch args]}]
    (-> (.getToken js/window)
        (.then #(let [dispatch-args (vec (concat [dispatch %] args))]
                  (rf/dispatch dispatch-args))))))

(defn reg-token-event-fx
  ([id interceptors handler]
   (let [with-token-id (keyword (str (name id) "-with-token"))]
     (rf/reg-event-fx with-token-id handler)
     (rf/reg-event-fx
       id
       interceptors
       (fn [_ [_ & args]]
         (cond-> {:get-token {:dispatch with-token-id}}
                 (not (empty? args)) (assoc-in [:get-token :args] args))))))
  ([id handler]
   (reg-token-event-fx id nil handler)))
then a handler definition looks something like this:
(reg-token-event-fx
  :search
  [app-state-spec-interceptor]
  (fn [{{:keys [search-text]} :db} [_ token]]
    {:http-xhrio {:uri     (str "/search?q=" search-text)
                  :headers {"Authorization" (str "Bearer " token)}
                  ...}}))

kelveden 2020-07-01T15:21:42.195500Z

It works great!

kelveden 2020-07-01T15:22:04.195700Z

So thanks @me1987!

mdallastella 2020-07-01T17:39:16.197100Z

It worked. It's not fancy, but it's a workaround.

phronmophobic 2020-07-01T18:47:45.198700Z

I feel like I must be blind. I'm looking for the explanations of form-1 and form-2 components in the new re-frame docs and can't find it anywhere. are form-2 components not recommended anymore?

dpsutton 2020-07-01T18:50:55.199200Z

i sent you a pm this morning asking about channels to donate to you individually. seems like you have notifications off though. just wanting to see if you had any way to get you some money from our development team

2020-07-01T18:51:21.199800Z

you can use subscriptions directly in form-1 components, I normally just deref directly @(rf/subscribe [...]) within let.

phronmophobic 2020-07-01T18:53:08.200500Z

I was looking for https://github.com/reagent-project/reagent/blob/master/doc/CreatingReagentComponents.md#form-2--a-function-returning-a-function, which is under the reagent documentation.

phronmophobic 2020-07-01T18:54:14.201300Z

I'm going through the re-frame todo mvc example, and was looking for the docs on form-2 components to under stand the todo-input https://github.com/day8/re-frame/blob/master/examples/todomvc/src/todomvc/views.cljs#L7

phronmophobic 2020-07-01T18:56:23.202Z

are form-2 components idiomatic in re-frame? is there a better alternative?

2020-07-01T18:57:52.202800Z

they use form-2 components there because they want to use ratoms directly for inputs, so the state is not changed while typing the text into it

2020-07-01T19:00:04.203700Z

I haven't ever used anything like that (we are dispatching all changes), so not sure about idiomatic way in Re-frame

phronmophobic 2020-07-01T19:03:03.205600Z

I'm pretty new to re-frame and I like the idea of sticking to form-1 components. Are form 2&3 components common for re-frame projects?

2020-07-01T19:04:28.207100Z

I think the change in subscriptions made form-2 unnecessary in most cases. In our code, we have almost all form-1 components, and a few form-3 components where we need to use React events like component-did-mount or component-did-update. If you are starting with Re-frame, just use form-1 for everything.

1💯2🤘
2020-07-01T19:05:38.208200Z

Beforehand, subscriptions has to be used in form-2 components because rf/subscribe couldn't be used for every rerendering which would cause memory leaks. But it was changed that it is cached now.

phronmophobic 2020-07-01T19:06:10.208600Z

awesome!

2020-07-01T19:07:06.208900Z

https://github.com/Day8/re-frame/issues/218 for history

2👍
lilactown 2020-07-01T19:09:36.209500Z

form-2 is still very relevant when creating local states

lilactown 2020-07-01T19:09:55.209700Z

not everything belongs in the app db 😄

2👍
2020-07-01T19:12:31.210300Z

what is something you would put into local state? like values of an input, as it changes?

dpsutton 2020-07-01T19:12:51.210600Z

collapsed/expanded state is something we have had there

lilactown 2020-07-01T19:13:40.211100Z

my rule of thumb is: if I deleted the UI, would this state still be relevant? if so, app-db. if not, local state

1👍
2020-07-01T19:13:42.211200Z

> Using @(rf/subscribe [:node/pos endpoint-id]) works within the main body of my subscription. So my question is what is the downside of using it like this? There's a possibility of memory leak because derefs are tracked and it is possible that subscription won't be disposed.

2020-07-01T19:15:07.213200Z

don't you get then into problems when something is local at first, but then you need it somewhere else? I found that impact of user interactions often influences very different places in the state of the app.

dpsutton 2020-07-01T19:15:40.213900Z

sometimes but not all the time

lilactown 2020-07-01T19:16:12.214600Z

you can either lift it up to a parent and pass it as props (an easy, purely mechanical change with the ratom API) or - maybe it's relevant outside of the UI

2020-07-01T19:18:00.216800Z

My experience is form 2 was required whenever I wanted animation with JS comps. (Material UI).

lilactown 2020-07-01T19:19:10.218Z

yes. UI state needs to have very low contention. you want the minimal amount of mutations & subscribers in order to remain fast

lilactown 2020-07-01T19:19:58.218800Z

app-db is just a free for all. as your app grows, every top-level subscription has to be run on every change. it's terrible for UI state

lilactown 2020-07-01T19:20:40.219700Z

but, there are benefits to having a single source of truth for your application domain

lilactown 2020-07-01T19:20:45.220Z

I'm very influenced by this article: https://medium.com/@mweststrate/ui-as-an-afterthought-26e5d2bb24d6

1👍
2020-07-01T19:21:39.221300Z

hmm, speed is a benefit, I like having all of the state within one atom which makes the app little bit more clear (we have now about 25k lines). Not sure how this goes when it grows.

lilactown 2020-07-01T19:22:55.221900Z

for us, our app is about twice as big and the app-db is an unmanageable mess

lilactown 2020-07-01T19:23:13.222300Z

you can't print it w/o performance problems lol

lilactown 2020-07-01T19:23:54.222800Z

the dev experience and tooling problem you're talking about is legit but there are ways to solve it that actually don't depend on keeping everything in one atom

lilactown 2020-07-01T19:24:56.223800Z

you could keep things in multiple atoms and have lil bit of code that allows you to explore them all at once

2020-07-01T19:25:21.224200Z

hmm, how about using inspect in shadow-cljs instead of printing?

2020-07-01T19:25:51.224900Z

makes sense, currently it doesn't feel to me like a mess yet and if it becomes a mess later I will have to rethink the approach

2020-07-01T20:37:58.225300Z

Ok, so I read this http://day8.github.io/re-frame/flow-mechanics/ and using reg-sub-raw instead makes sense for my case. Btw. I am missing a real example which would need reg-sub-raw in the text. The example here is better: https://github.com/day8/re-frame/wiki/Dynamic-Subscriptions

2020-07-01T20:38:08.225600Z