architecture

Mateusz Mazurczak 2025-01-16T11:39:36.264249Z

Hello everyone, I have front-end architecture design question related to reagent and re-frame. I'm really into the stateless UI idea (@christian767 has great materials on it: https://cjohansen.no/stateless-data-driven-uis/ and his talk https://2023.javazone.no/program/85f23370-440f-42b5-bf50-4cb811fef44d) I'm really fond of the idea that you can simply have that flow of: Data you need for the view (no matter where from) -> Data processed to fit UI components needs -> UI components decoupled from domain logic I'm trying to fit it with re-frame framework, I've separated the data comming in upfront, I've created subscription that on data change prepares the data for the UI and I have seprated the UI. I coupled UI with re-frame dispatch (e.g. on click) that they dispatch events, so the data for the UI is pure with actions (e.g. click) on the components are just vectors of events to propagate and manage in re-frame. But the problem with this top->down approach, is performance, because small change on the UI (e.g. filling one input form that's inside 3 levels deep of application) is refreshing all the data, one thing affecting performance is processing of the UI data as a whole (which could be optimized comparing some diffs) and the other is react checking and updating all items from parent to the child even when they didn't change. So imagine we have on router Settings view, which has inside Multiple different views and one of them has maybe some more categories and one of those changes. If we gather data via subscribe at the beginning of Settings view, small change deep-inside refreshes all the components. So e.g. we have data like:

{:settings {:migrations-section 
              {:title "..." 
               :description "..." 
               :migrations-comp {1 {:some-data "..." :ui-status :smth :on-click [:run-migration {:id 1}]} 
                                 ... more items}
               ... some data about other comps here}}}
^ That is created at the beginning of settings-view and subscribe to changes If something inside one of migrations-comp children changes (e.g. ui-status) We have subscribe at the top-level so it will refresh it there and react will go over all children In contrast to more entangled view where there is subscribe in-front or even inside each migration list element, change of one migration-comp data will trigger subscription only there. I really like the separation of concerns and clear data transformation, but this will be problematic due to performance in some views when they are bigger. Which will create a need to break that format. I wonder if someone tried to do this with re-frame, have some experiences how this plays long-term or some ideas how this could be managed. I was wondering about splitting this a bit e.g. maybe passing subscription down the line as a data, but this seems as a bit weird idea, coupling things even more with re-frame on lower levels making it check if e.g. there is [:subs ...] also making it harder to get what data gets there and raises questions to structure (For example, if we have list of items and don't ask for all list items first, we only know there are items there, that needs to be re-packed into specific item UI data and it raises questions how it should be than defined for the children upfront. Which makes it complicated, and we are not getting the benefits of the split)

phronmophobic 2025-01-16T20:02:47.076779Z

I haven't tried it with re-frame, but I take a similar approach using a different library. The key idea is caching previous renders which works well when inputs and outputs are immutable data structures. As long as the UI isn't completely changing every frame, then most of the work from the previous frame can be reused. Is there a reason you're not using https://github.com/cjohansen/replicant if you're trying to implement the ideas from those talks?