Fork me on GitHub
Andreas Edvardsson08:06:03

Hi, I have not quite gotten the hang of Fulcro yet, and am a bit stuck on the issue outlined bellow. I'd be grateful for any ideas, thoughts or suggestions you might have. 🙂 Background: I have a basic layout with "cards" on one side and a map on the other. Each card contains some information about an entity, possibly containing lists of other entities. The user can open, close and navigate to any number of cards, including having multiple copies of the same card open at any instant. The wish: Render points/markers/lines/etc on the map based on what cards are open. The problem: Each card-type should be rendered on the map in a certain way, for example as a marker, as a line or as a combination of things. Ideally I imagine the logic about what to show and how to show it should reside in the card defsc:s themselves, in order to preserve local reasoning. Alternatives I've considered: 1. Run a post-mutation at card events, looping through all open cards and update some state based on that. The map is passed said state as a prop and updates accordingly. Negative: Logic separated from components, possible ouf-of-sync issues. 2. Whenever a card is opened/closed, also maintain a corresponding visualization component. Then proceed similar to alternative 1, looping over visualizations instead of raw cards. Positive: Logic is closer to the card. Negative: Possible out-of-sync issues and bookkeeping as in 1.


@danvingo I have been using react-three-fiber can recommend it.


very nice - what type of scenes you rendering? data viz or art or games??


@andreas179 I'd also keep most of the logic inside the components themselves, you could probably get away with using component local state if your logic doesn't get too expansive. A lot of how you would structure this depends on which map library you're using and how well it plays with the "react component" way of working.

Andreas Edvardsson09:06:11

Thanks for the input! I'm using react-map-gl together with layers for visualizations, so it's fairly reactive. However, propagating some derived version of the data from the card components to the (singleton) map component in a nice way is what i'm struggling with here. I'm not entirely sure of how local state would help me, but I'll do some more thinking


ah, I've been using with cljs for 2 years now 🙂


it's a great library


so you have cards with a bunch of geo data and a layer type associated with them, and adding them represents a new layer for deck right? With component local state I mean things like set-state! or update-state! you could save the actual geo-data + layer type or their ids and turn that into deck layers. You can pass down layers or data as props and the callbacks to update the state with comp/computed


so you have the local state in a parent component to both the deck component and the cards


and pass the callback to update the state to the cards

Andreas Edvardsson19:06:28

Right, I see what you mean now:) that could possibly be an option. I think I have a few different ideas to try out now. Really helpful to bounce ideas back and forth at times! I appreciate it!

đź‘Ť 3

For those of you being completely annoyed by the new “Smart command” crap in the Terminal of IntelliJ: Here’s how you can turn it off globally:

đź‘Ť 3

How do I define new keys for the defsc option map? In a way that a function gets called with its contents and what-have-you so I can e.g. route to somewhere else. I am not sure how this functionality is called, so I don't know where to look for it... I want it for a rather simple check if users are allowed on this page, and if not redirect them somewhere else


This gives you the raw keys off the options of defsc


How do I route to the root router itself? If I do (dr/change-route APP []), I get ERROR [com.fulcrologic.fulcro.routing.dynamic-routing:598] - Could not find route targets for new-route


There is no such thing


dynamic router’s composition requires you to route to TARGETS, not routers


Think of it like web servers: / means nothing to apache/nginx/etc. It isn’t a resource. You have to define some kind of “default” or “redirect” in those to name what actual resource you want


So, if you want [] to mean ["index"], then add in a transform function in your routing to make it so

đź‘Ť 3

Thanks. Is it okay to just do this?

(defonce history (pushy/pushy (fn [p]
  (case p
    "/" (route-to! "/main")
    (dr/change-route SPA (log/spy :info (-> p (s/split "/") rest vec))))) identity))


The defmutation code and the defsc code refer to each other a lot. When having a code structure where these two are split into different namespaces, how can I avoid circular dependencies?


you need not ever refer to a mutation ns in the UI, since mutations are just data. It’s merely convenience.


You can leverage declare-mutation to get back the convenience.

đź‘Ť 3

@U6SEJ4ZUH trying to understand, what are the use cases where u have to call defsc from mutation. Most mutations can be generic, like the inbuilt ones - mark-complete!, merge-component, load etc You cand call them from the component, and pass the component reference in it. So these mutations dont have to know about the specific component.


See also component registry


the fully-qualified keyword version of your classname can be used to look it up


registry-key->class I think

đź‘Ť 3

Come to think about it. Maybe having the mutations referring to UI is a bad idea? Since the model should not be locked with a particular view? Does that ever come up as a problem for you in large apps @U0CKQ19AQ? Thanks!


If I want things decoupled I’ll just delcare a UI-less defsc in the mutation ns for normalization…but typically your I/O is specific to particular UI. That said, UISM abstracts the UI away into actors, as an example of how you can generalize things further. RAD uses that to make it possible to write all of the read and write logic once for every possible form/report.

đź‘Ť 3

Hi, fulcro newbie here! i am trying to get my head around how to put data to the db. Reading the manual there is

(merge-component! app Person {:person/id 1 :person/address {:address/id 42 ...}})
but doesn’t this tight the process of loading the data with the view? what if you have 2 different Person Components; let’s say Person (just showing first and last name) and a PersonDetails showing First name, last name, Gender. does the programmer need to know which component has a superset? what’s the difference with just doing?
(df/load app [:person/id 1] Person)


You can make other defsc components without any ui. One of those could be a superset that you use specifically for merging. I have several components like that in a ns called xxx.model.idents.cljs


Got it, basically components that describe your data. Makes sense. Thanks


Components are the core of Fulcro's data management. Creating a UI is a secondary (though important) and optional role. They essentially describe your domain entities. So there is nothing wrong with the programmer having to know which to use. And, as suggested, you can have some non-ui ones for these purposes.