This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2021-07-26
Channels
- # aws-lambda (15)
- # babashka (7)
- # beginners (124)
- # calva (7)
- # cider (19)
- # clj-kondo (26)
- # clojure (261)
- # clojure-australia (3)
- # clojure-dev (10)
- # clojure-europe (45)
- # clojure-nl (4)
- # clojure-uk (6)
- # clojurescript (10)
- # datomic (7)
- # depstar (7)
- # emacs (11)
- # fulcro (41)
- # graalvm (48)
- # helix (1)
- # honeysql (17)
- # inf-clojure (7)
- # introduce-yourself (3)
- # jackdaw (2)
- # lsp (36)
- # malli (2)
- # meander (2)
- # membrane (1)
- # missionary (11)
- # off-topic (17)
- # pathom (83)
- # polylith (15)
- # re-frame (31)
- # reagent (42)
- # sci (35)
- # shadow-cljs (13)
- # spacemacs (13)
- # sql (19)
- # timbre (3)
- # tools-deps (77)
I’m trying to delete [:trello-card/id "5a0f9851615fa324ca46ec7e"]
from ident [:trello-list/id "5b1b3a29d7ce069c0b61ba6c" :trello-cards].
But when I do this, nothing happens — I expected the trello-card/id
to be deleted from the table (and of course, the element to be removed from the DOM).
Trying to figure out what I’m doing wrong… Thx in advance!
(swap! state merge/remove-ident* [:trello-card/id "5a0f9851615fa324ca46ec7e"]
[:trello-list/id "5b1b3a29d7ce069c0b61ba6c" :trello-list/cards])
PS: if I can get this working, I feel like I’ll have learned how to do 80% of what I need to do in Fulcro! (I’ve learned how to load data from queries, render them, update them, and hopefully soon, delete items.)it looks like :trello-list/cards
is denormalized; it should be a vec like [[:trello-card/id "abc"] ...]
, aka edges to idents like [:trello-card/id "abc"]
. what does your trello-card component look like, and how are you loading that data?
IOW an ident is a place to which data is loaded. an edge is a pointer to that place. right now it looks like you've got the data itself under that attribute instead of a vec of pointers
Huh…. I see what you’re saying about the shape of trello-list/cards
not being right. Not sure what’s happening — it’s loaded in by this:
(comp/defsc Card [this {:trello-card/keys [id dateLastActivity idList idBoard
pos name desc due]
:as props}]
{:query [:trello-card/id :trello-card/dateLastActivity :trello-card/idList :trello-card/idBoard
:trello-card/pos :trello-card/name :trello-card/desc :trello-card/due]
:ident :trello-card/id}
)
Which is loaded in via this component: SelectedListCards
:
(comp/defsc SelectedListCards [_ {:trello-list/keys [id name cards]
:as props}
{:keys [on-select selected]}]
{:query [:trello-list/id :trello-list/name :trello-list/cards]
:ident (fn [x] [:component/id ::SelectedListCards])}
Oh!!! The problem is right there in the :query for SelectedListCards! It’s missing the comp/get-query
.
This works! Thank you @U797MAJ8M!!
Yay, now you’re at 80% - celebrate. I’m about to dig into Fulcro like you and enjoy your comments along the way.
If you use Card inside the SelectedCardList then https://github.com/holyjak/fulcro-troubleshooting would have warned you about the omission, I think
Yes, indeed, @holyjak! I used your fantastic guide to zero in on the problem! Thank you!
Good to hear, though in this case I didn't mean the guide but the tool (of the, confusingly, same name) :)
Which gets me to the other thing I noticed — also diagnosed using @holyjak’s fantastic guide.
When I click a button to call the mutation that calls remove-entity
, the UI updates. Hooray.
But when I manually call the function in a REPL that does the remove-entity
(which the mutation calls), the updated DB shows up in Fulcro Inspector, but the UI doesn’t change. ???
As @holyjak recommends, when I call force-render!
, the UI updates.
I’m trying to figure out who the UI doesn’t update w/o that force-render!
… (Part of me doesn’t care, but I feel like I need to understand this to truly understand the Fulcro way. 🙂
I think that when you transact!
(unless you transact!!
) then Fulcro schedules a render afterwards. Could that be it?
I'm working through the Fulcro Exercises and 6 Client-side mutations
is throwing up a warning in my console when I either Select All -> Delete
or manually select each player on a team and delete them all:
react_devtools_backend.js:2574 Warning: A component is changing a controlled input to be uncontrolled. This is likely
caused by the value changing from a defined to undefined, which should not happen. Decide between using a controlled or
uncontrolled input element for the lifetime of the component. More info:
at input
at ctor ()
at label
at div
at holyjak.fulcro-exercises/Team
at form
at holyjak.fulcro-exercises/Root6
It looks like the solutions also raise the same warning. Is this warning something I should be concerned about and need to understand better?Thank you! I'm not sure how serious problem this causes to React. We have somewhere nil where we should instead have a value such as false. I'll have a look.
Here is the fix https://github.com/fulcro-community/fulcro-exercises/commit/e63ff226b6e62251535fbae450b32fe704c5ae9a
I forgot that and
can return nil
🙂
Hello, guys, please help. I'm using RAD and added simple defsc
component. But I don't understand how to feed props in it.
(defmutation bump-number [ignored]
(action [{:keys [state]}]
(swap! state update :ui/number inc)))
(defsc Rom [this {:ui/keys [number] :as props}]
{:query [:ui/number]
:initial-state {:ui/number 5}
:ident (fn [] [:component/id ::Rom])}
(dom/div
(dom/h4 "This is an example.")
(dom/button {:onClick #(comp/transact! this [(bump-number {})])}
"You've clicked this button " number " times.")))
I know the others have answered your question, but just an add. I can tell from the code you posted that you have not yet understood the tree of initial state and how props are fed to the UI. The way I can tell this is you said nothing about how the component is composed into the app. A lot of people have this misconception. Standard Fulcro components are normalized and easily refactored, but they are not stand-alone. They must be composed into their parent correctly. This is the #1 misunderstanding (about 95% of problems people have is with this misunderstanding). The data for a component ends up AT the ident in the db, which is how they can tell that your mutation is wrong (swaps in mutations will almost always be a swap on an update-in of a path of length 3 (the ident is 2, and the prop you want to change has a name, which makes 3).
Try reviewing the basic materials in the YouTube video..if you haven't yet watched those
Another quick note: If you transact!
on this
(the component), then the env
of the mutation will include ref
, which will be the ident of the component that invoked the mutation. That is how general mutations like m/set-value!
are written.
Thank you @U0CKQ19AQ !, I have fixed it. The main problem for me was to understand that I should `collect` initial state from children in the root component and then to feed `props` to children
It doesn't display initial
number and doesn't display incremented ones. But I can see in Fulcro Inspect changing of ui/number
I think you read and write at different places. You mutations sets DB -> :ui/number
while the component reads DB -> :component/id -> ::Rom -> :ui/number
. Check again the sections on idents and normalization, perhaps.
I had trouble with the same thing — check out how I was able to implement this in the RAD template here:
https://github.com/realgenekim/rss-reader-fulcro-demo/blob/gene-stories/src/shared/com/example/ui/button_toys_form.cljc#L18
I think the problem is the ident in your bump-number
— the ident should be [:component/id ::Rom :ui/number].
Right now, you’re incrementing something outside of the “lexical scope” of the Rom component. (Exactly the same mistake I made, before talking with @U0CKQ19AQ.)
(I see now that I’m saying exactly the same thing as @holyjak is. 🙂
Noteworthy - there are better solutions than a dedicated mutation, namely https://cljdoc.org/d/com.fulcrologic/fulcro/3.5.1/api/com.fulcrologic.fulcro.mutations#set-integer! (beware - just call it, do not wrap in transact). This will ensure you change the right place. See its impl.
Thank you guys! I have fixed it. The main problem for me was to understand that I should collect
initial state from children in the root component and then to feed props
to children
If you have ant tips how to make that easier to understand in the https://fulcro-community.github.io/guides/tutorial-minimalist-fulcro/index.html, pls let me know! This is essential.
I didn’t even know about this mini-guide, I need to read it first, thank you for the link
BTW, we're you aware of the Fulcro Community site? If not then how to make it more visible?
As I see now there is the link in the Fulcro book at the beginning. But I rarely look at that section, I look at the left content navigation part for particular things. So maybe it would be useful if there would be a section, for example, "Useful links" or "Other tutorials" or even directly "Fulcro Community Site" (And in the Fulcro RAD book as well). Also I think the problem is that "googling" "fulcro" doesn't show the community web site at first page.
Thanks for all the help getting entity deletion working! Which gets me to the other thing I noticed — also partially diagnosed using @holyjak’s fantastic guide. When I click a button to call the mutation that calls `remove-entity`, the UI updates. Hooray. But when I manually call the function in a REPL that does the `remove-entity` (which the mutation calls), the updated DB shows up in Fulcro Inspector, but the UI doesn’t change. ??? As @holyjak recommends, when I call `force-render!`, the UI updates. I’m trying to figure out who the UI doesn’t update w/o that `force-render!`… (Part of me doesn’t care, but I feel like I need to understand this to truly understand the Fulcro way. 🙂
Fulcro does NOT watch the db atom (Inspect does). Fulcro is a strict transactional system. If you don't run a transaction, as far as it is concerned there is no UI to update.
So, if you want to run something in the REPL, the thing you want to run is transact!
, or something that wraps it (as does load!
, merge-component!
, set-value!
, etc. Everything you call that changes something to do with the state db in Fulcro results in a transaction underneath...just trace the source and you'll quickly reach where it is doing a transact. load!
for example, defines an internal-load
mutation and when you call load!
it submits a transact on internal-load
.
https://clojurians.slack.com/archives/C68M60S4F/p1627327328105600?thread_ts=1627258680.097100&cid=C68M60S4F
Oh, that’s interesting! From Fulcro book: “comp/transact! The central function for running abstract (possibly full-stack) changes in the application. Can be run with a component or app. If run with the app, will typically cause a root re-render.”
Huh. I now see that merge!
doesn’t force render, either.
Just comp/transact!
. And df/load!
, too, right? (ah, thanks for answer — `load!` forces a transaction.)
THANKS!!! Another Fulcro mystery solved.
ooops. That's right. Some of the merge functions are meant to be used as utilities within a mutation.
merge!
isn't really meant for public use...it's a very old function that was part of the original implementation mixed with Om Next, and I could not remove it without breaking external code (because it was public). So, even though I didn't really want it to be public still, I was stuck doing so because I don't like to break existing code if at all possible.
It does not hurt anything, but as you noted it does not force a render. These functions are part of the implementation of the load logic (which is already running in a mutation) which is why they are not, themselves, written as transactions.