Closed bago2k4 closed 6 years ago
hey @bago2k4, the question makes perfect sense and probably this should be documented more explicitly in the README.
What is intended in this case is something like the below:
(def drv-spec
{:db [[] *db-atom]
:selected-post [[:db] (fn [db]
(let [post-id (get-in db [:post-id])]
(get-in db [:posts post-id])))]})
As you can see the post ID that you want to select should be part of the app state.
This also works quite well when combined with routing state as in the following example:
(def drv-spec
{:db [[] *db-atom]
:route [[:db] (fn [db] (get db :route))]
:posts [[:db] (fn [db] (get db :posts))]
:selected-post [[:route :posts]
(fn [route posts]
(when (= (:handler route) :post/by-id)
(let [post-id (get-in route [:route-params :post-id])]
(get posts post-id))))]})
Let me know if this helps :)
Hey @martinklepsch thanks for the fast reply, i see where you are going there and that works when i'm looking at a specific post.
But if i have a component called blog
for example that renders a list of post
s i need to pass the latter the data as props, there is no way i can get it from derivatives, right?
It would be a great improvement IMO.
Also if you think that each post
has a list of comment
s you need to pass those as props too.
WYT?
Why would you not pass the data as props? I think passing data as function arguments yields much simpler to understand components than components who rely on global context like derivatives. This also applies to similar mechanisms such as re-frame subscriptions.
Combined with rum/static
components who receive identical props also won’t rerender.
Because sometimes the parent component don't (or should not) have all the data, take the blog example above: the blog
component doesn't need all the comments data, only the posts. If the comments are stored in another place of the app-state i have to load all of them in the blog
component to pass them to the post
and then to comments
.
Can you see where i am going?
It's not something you can't do in other way but with derivatives it would be better i think.
I really don't know if this is possible, the spec key would be dynamic and available only at runtime so building the spec graph maybe is not possible or not performant enough, but i don't know the derivatives code enough well.
Thanks for the example, I think I see what you mean now.
So basically I think that in a case like this it is preferable to pass more data to a component (i.e data for its subcomponents) than to have components use derivatives. You can have a derivative that combines posts and comments and comment authors in a way that is suitable for rendering and then pass that data down the component tree.
I understand that this is probably less intuitive than just having a dynamic derivative but it has a couple of benefits:
Also keep in mind that duplicating data as part of the derivative function (e.g comment authors) has basically no cost due to structural sharing between Clojure datastructures.
To circle back to dynamic subscriptions: derivatives does not and likely will not support them. This was a design decision early on made based on the benefits given above.
I hope I was able to convince you of the benefits of this approach 😊
Yeah sorry i should have been more clear with my example from the beginning.
Anyway my is more a question then an issue, i wanted to know if something like this was already contemplated by derivatives and if not if it was a plausible feature request.
I'm not saying that using props is wrong, i just wanted to ask you.
Thanks for your replies, closing the issue.
Got it. Thanks for asking it’s been a good exercise to think about this again :)
Since the code you’re working on is probably open source feel free to ask whether specific usages of derivatives are idiomatic. Maybe there’s something where you’re wondering if a problem could be solved better?
I'm trying to render a list of posts and what i need is to pass each post it's own data only that i have as a map inside the app state. Now i know i can create a derivative like:
(drv/drv :posts)
to pass the whole list of posts, but what about the single post? right now i can't do something like(drv/drv :posts post-id)
or like(drv/drv (keyword (str "posts-" post-id)))
. The main problem is that i don't know the post IDs before i load so i can't create the derivative spec for each of them. Passing all the posts to each component is not very good for performance since it re-render every time something change in the whole list of posts.Thank you