Fork me on GitHub
#re-frame
<
2018-07-15
>
mikethompson02:07:07

@p-himik you've been involved in a fairly long-running series of questions (I've not followed all the ins and outs). Have they all been answered? I'm happy to have a go at answering anything you feel is unresolved if you want to re-pose the question.

p-himik02:07:14

@mikethompson Let me think... 1. re-com implements most components as (fn [& {:keys [...]}] ...). How is it better than (fn [{:keys [...]}] ...)? 2. I did have a few questions about subs, but I think they essentially boil down to one. Is there anything wrong with (r/reaction (or @(subscribe [:a]) @(subscribe [:b])))? If there's nothing wrong, I suppose there should be something with

(let [a (subscribe [:a])
      b (subscribe [:b])]
  (r/reaction (or @a @b)))
? Like the :b sub will not be disposed of or something like that. And not really a question, just a wish - it would be nice to be able to more easily extend re-frame. Namely, in order to implement something akin to db-handler->interceptor, right now I have to copy the whole body of db-handler->interceptor and change it despite that other similar functions in re-frame have pretty much the same body. Another such thing is the path interceptor - if I want to implement something just a tad different (e.g. a path that resides in db), I have to copy it completely. There're probably other places that could be improved by refactoring.

mikethompson02:07:30

Answer to 1. Hmm. Its all a while ago, and I don't remember all the reasoning for the decision. It would take a while to swap it back into memory. Perhaps this ... go to the docs/demo: https://re-com.day8.com.au/ and look for "Introduction" / "Uses Named Parameters " There some explanation on the right hand side.

mikethompson03:07:07

Answer to 2. There's nothing "wrong" with your suggested:

(let [a (subscribe [:a])
      b (subscribe [:b])]
  (r/reaction (or @a @b)))
Nothing wrong in the sense that it will work (the reaction will rerun depending whenever one or more of the subscriptions/signals change) but your further question as to whether :b be disposed or not depends on the way this reaction is used.

p-himik03:07:23

Regarding parameters - so it appears that the only advantage over a plain (non-varargs) map is that if you don't specify any parameters at all, you don't have to put an empty map there. But there're disadvantages - like the absence of neat automatic formatting and the need to use apply concat when you need to pass these arguments somewhere down the line without unpacking. Regarding subs - if :a always resolves to true, how will :b be disposed of if it's never dereferenced?

mikethompson03:07:49

Okay, back to Answering 1 I seem to remember we went for this approach because we wanted to minimise the amount of syntax (braces of various kinds). We prioritized the cleanness of code, the ease with which the code can be laid out and read. I think that was it. I appreciate that others may prioritise other aspects of the design, but that was important to me. I, for example, love Python's significant whitespace, because it minimise the "noise" of brackets. Shrug.

mikethompson03:07:57

The view part of our code is by FAR the most voluminous. So we wanted maximum cleanness on that side.

mikethompson03:07:03

I think that was the thinking.

p-himik03:07:39

Agree about Python. Although habitually pressing a button to autoformat current file in my copy of re-com leads to a disaster this way. šŸ™‚

šŸ˜ƒ 4
mikethompson03:07:03

I haven't been doing much ClojureScript coding recently, but we use Cursive and we don't have any formatting disasters (that I've been told about). All seems to work. This might just be a tools thing.

p-himik03:07:54

I use Cursive as well. It just doesn't understand that [view-fn :arg1 val1] needs to be treated as a function. Its author promised to think about it though.

mikethompson03:07:29

Hmm. Not sure. Like I said, noone ever seems to have a problem in our team.

mikethompson03:07:52

Back to answering 2, Yes, you are right. The :b will not be "disposed of" if :a is True. Some related discussion here: https://github.com/Day8/re-frame/issues/218#issuecomment-252470445 You are effectively highlighting "Corner Case #2" Using: 1. reg-sub often takes away the problem (this you probably already know, but worth repeating, just in case) 2. embedding subscriptions in Form-1 is the other part to taking away the problem (which is what the linked-to issue is exploring)

p-himik03:07:15

Thanks for confirming. My current concern with subs is that I have two subs, and the second depends on the value of the first one most of the time. The issue is that the second sub is really complicated (a completely rewritten sub from subgraph), so I can't just compose their functions. So, I was using

(r/reaction (let [v @(subscribe [:a])]
              (when (check v)
                @(subscribe [:b v])))
as a new sub signal.

mikethompson03:07:36

Sure. I wrote reg-sub precisely because there were some subtleties within using raw reactions.

mikethompson03:07:38

I'm open to a docs PR which adds more info/warnings to the current descriptions of reg-sub-raw

p-himik03:07:50

Will keep in mind. šŸ™‚ Thank you!

adam16:07:45

I am new to re-frame and not quite sure how to build a user authentication/authorization system with it. From what I gathered I should create an auth interceptor and place my auth logic inside :before section then inject the interceptor into every events reg-event-db and reg-event-fx that I want to protect. Am I on the right track?

šŸ‘ 4
manutter5117:07:44

That sounds good as far as it goes, but Iā€™m a little leery about doing auth stuff on the client side, since a hacker will just spy on your client and then call directly to your server. If youā€™re doing auth checks on the client just to avoid wasted trips to the server, thatā€™s fine, but the server needs to implement the real protection.

adam17:07:24

@manutter51 for sure, it's just to visibly hide the parts that aren't accessible for the logged in user - not for security

manutter5117:07:14

Yeah, thatā€™s cool then. Iā€™m not sure Iā€™d use an interceptor for showing/hiding stuff. Iā€™d just have the server return a set of roles for the current user once theyā€™ve logged in, and then have some code like

(defn restricted-widget [] 
  (let [roles-set (rf/subscribe [:current-user-roles])]
    (if (:can-view @roles-set)
      [:div.admins-only ...)))

manutter5117:07:34

Thatā€™s head-code, please disregard any bugs/typos šŸ˜‰

manutter5117:07:08

The reason Iā€™d prefer that approach is so when I come back in a few weeks and have no clue what I was thinking when I wrote it, I can just read the code and see that ā€œoh, Iā€™m only displaying this div if the current user has :can-view in their current user roles.ā€

manutter5117:07:14

Actually, I donā€™t think youā€™d need to put interceptors on your events (?), assuming youā€™re hiding anything that might dispatch ā€œillegalā€ events anyway. But thatā€™s me assuming, so disregard as appropriate for your particular use case.

adam17:07:11

@manutter51 Thank you, that makes a lot of sense actually. I will give it a try.