reagent

awb99 2024-10-28T19:29:57.347789Z

I am struggling to implement this simple pattern in reagent: (defn person [person-id] [:p (:first-name person) " " (:last-name person)).  What I would like to do is do a fetch to get the person with the person-id before displaying the data. I did implement this with a level-2 component, where in the render function I would do a new call to load data, in case the person-id is different. So I have one atom with the data and another with the last fetched id. I dont think this is clean code, so I tried implementing it in a level-3 component, where I have the fetch on mount and on update. However, it would trigger a permanent rerender; I assume because I was using the result atom in the reagent-render function. Does someone have a clean approach to this issue? I assume this is a very general problem.

p-himik 2024-10-28T20:09:18.882969Z

Hi. Please use code block formatting - Slack has a button for it in the UI, alternatively you can surround your code with triple backticks (the symbol underneath ~ on US keyboards, put three of them on their own line, then your code, then another three on their own line).

p-himik 2024-10-28T20:10:40.111399Z

> it would trigger a permanent rerender We'd need to see the code to explain why it does what it does. > Does someone have a clean approach to this issue? Personally, I just use re-frame to deal with all that stuff.

p-himik 2024-10-28T20:24:33.819519Z

I meant putting only the code into a code block, not the whole post. :) Scroll up the main chat to see how it looks when others do it.

awb99 2024-10-28T23:46:15.870089Z

@p-himik when using reframe you have the same issue: you need to subscribe to a person-id that can change. If you use a form-2 for this then you will not resubscribe to the new id. You have even more issues: you need to manage removing data from the aoodb when the person-id changes.

p-himik 2024-10-28T23:50:59.230069Z

Re-frame has an opinion on how to do things, and you don't do anything on render. Instead, you do things along with what has resulted in a render. So, for example, suppose you have a panel that's shown only when :visible? is truthy, and that panel needs some data to be fetched. Instead of fetching that data when the panel is mounted, the "re-frame way" dictates that you fetch that data when the value of :visible? is changed from a truthy value to a falsey value. Cleaning up app-db (which is often not necessary) is the same - just do it in the reverse direction.

awb99 2024-10-28T23:52:59.918599Z

That makes sense! Thanks @p-himik I need to reflect on that. It's a brilliant idea I never thought of.

awb99 2024-10-28T23:55:33.758329Z

So you say "render as you fetch" vs I suggested "fetch as you render".

p-himik 2024-10-29T00:00:33.282969Z

Yep. Re-frame has excellent docs on the matter.

awb99 2024-10-29T00:06:43.459459Z

So what this means is I don't use a level-2 component (defn person-ui [id] (let [person (rf/subscribe [:person id])] (fn [id] [:p (:first-name @person)])). Instead you use (defn create-person-ui [id] (let [person (rf/subscribe [:person id])] (fn [] [:p (:first-name @person)])).

awb99 2024-10-29T00:16:06.634409Z

The second Version is a parameterless reagent fn. So it can never be called by react with other person-id the first Version would always Show ui of the Person-id at creation time. If I say have a combobox to select a Person then react would show it correct the first time. The seconf time it would Reuse the mounted component and therefore Show the first person.

p-himik 2024-10-29T07:49:16.626769Z

It's all documented with a lot of examples. Just use a form-1 component, subs are cached and cheap.