Fork me on GitHub

I'm trying to get nested subscriptions to work and didn't want to name everything all the way down the tree. Given this example I could make subscriptions for [::field-login :email] that just seems inefficient.


I use namespaces for that, instead of using filesystem-based keywords (i.e. instead of ::login, etc). So for example I have :db/forms which is a map to all my app’s forms (:forms db), then I have a login form at :forms/login-form, then my username field is :login-form/username, and so on.


But then you're making subscriptions for every field on every form?


Yes, but that has certain advantages, because it isolates the fields from each other, so that when you type in one, it doesn’t re-render the others.


Alternately, you could probably make a function that would take a nested map of fields, and auto-generate the subscriptions using a similar naming scheme. reg-sub is just a function.


I’ve never actually done that because I like writing out the subscriptions as a form of “executable documentation.”


I had made a simple form, now I'm adding new ones, and its getting hard to read.


It’s a little boiler-platey, but I’ve been burned by too much “magic” code not to have a strong preference for explicit declarations for things.


My thought was, I have a view that is a login form. It know's its a login form. Why does it have to subscribe to [:login-email-value] instead of just [:email-value].


I'm a bit confused by your nested namespaces...I thought you could only go 1 level deep like

{:login-form/fields {:pass "" ...}
 :new-form/fields {:pass "" ...}}


You mean in your app-db? No, you can nest things arbitrarily deeply.


I have a certain personal philosophy of how I like to write re-frame apps, and I discussed it a fair amount in the talk. It’s not scripture or anything, but it might be useful to some people.


I know I can nest maps, but I can't nest namespaces like :forms/login-form/username


You could do :forms.login/username

☝️ 4

The advantage of using names like :login-form/email is that it lets you also have a :refer-a-friend-form/email etc without conflict, which is important because you can subscribe to any subscription from anywhere in your app.


@manutter51, amazing content. Thank you!


Thank you! 🙂


Oh, wait. It is you!


Ironically I’m sitting here wearing the exact same T-shirt today too


I’m cool. 😏 So nice to meet you sir!


Can I use this mental model for the design big projects ?


What are pros and cons ?


Well, this particular arrangement is really good for GUI-type stuff. Once you get into the server side of things, it’s not quite the same fit (much as I wish it were).


I’ll probably responsible for a big project’s Front-End. I think, it can work.


Yeah for front end stuff it’s great.


What are the odds ? What are the worst case scenario ?


Well, the alternative is Fulcro, which does a lot more in terms of building a robust, well-connected back-to-front application, at the cost of an increased learning curve. People like it and use it for some pretty sophisticated stuff, and it evolved out of Om, so it’s got a great pedigree. So far I haven’t encountered any situation where I wouldn’t prefer re-frame though.


Also...Thanks for sharing that talk. It made what you were saying clear. Namespaces for subscriptions and events, but a simple nested structure for the app-db. That's what was confusing me.

👍 4

The one rough spot is that sometimes you want to access the value of a subscription from inside an event handler, and that’s generally tricky to do, because of how subscriptions work.


If I’m wrong, please correct me. app-db is a clojure data structure. Subscribes are just a fetcher functions for the DB. I think, every Subscribes you have defined as a stand-alone pure functions. You can test them, you can use them in the Events or Subscriptions you have. Is this mental model wrong ?


Subscriptions can’t be used in events, but you can chain them as you did before to get a nested value in a subscription


@scknkkrer There’s some subtleties in how subscriptions are implemented that makes them not play nicely inside event handlers. Subscriptions are more than just fetchers, they’re fetchers that trigger your component to re-render whenever the value changes. Event handlers aren’t components, and don’t have anything to render, so you can see how some things might go astray there.


Or actually, there’s a re-frame FAQ that goes into more detail, and points to a 3rd party library you can use to pull subscriptions into an event handler.


In practice, I’ve found that most of the time, I can write a function that does what I need to do, and then have the subscription and the event handler both call the function.

💯 4

That way you end up with the same value no matter where you start from.


I’ve just finished your video. Amazing! Thank you, sharing the knowledge @manutter51!


Thanks, glad it’s useful!


I was meaning that, creating pure functions that we can test, manage easily and use them in Subscriptions and Events. In both cases, one function to use everywhere. That let’s you end up with maintainable code-base.


Yeah I agree, that’s the best approach.


I’ve an idea about your presentation topic. I’m writing a book about Clojurescript. Not a fan of Writing UI or Designing UX but, I know I have to write a chapter about it. I think I’ll mention you and your ideas. If you let me.


Sure, go ahead


I’m just building on what others have contributed, more than happy to see that process continue


am i understanding re-frame 10x in that it is always one epoch behind current?


i.e., you need to make a state transition to find out what the state was before the (final) transition?


No, I don't think so. But if you just opened it, there won't be enough information there and you have to fire some event so populate it.


Yea it’s really strange. I put a console.log in my secretary event handler which fires a re-frame event and that logs upon first load but apparent 10x isn’t loaded then and doesn’t sniff that out. Then from there on, it always seems like it’s one state change behind what’s actually going on in the app.


Huh. I don't see such behavior in my projects. Maybe something in your code is interfering with 10x? Or maybe your 10x setup is somehow wrong. I'd try to create the smallest app with 10x and see how that works.


Yea I have a lot of stuff going on. Figwheel-main, tools.deps, cider, devcards, reframe, reframe 10x etc etc


Also, secretary and goog.history manipulation