Fork me on GitHub
#fulcro
<
2022-12-27
>
Jakub Holý (HolyJak)22:12:57

@tony.kay I’d love to understand why my attempt at form-in-modal did not work. I have CreationModal quite similar to yours, only with use-component directly on the form (which, in my case, was hardcoded). The thing I do not understand is that this use-component call returns props with just three keys: ../options-cache, .../active-remotes, .../asm-id . As far as I understand, the key fn that constructs this is rc/get-traced-props . When I call that, with the same input, in the REPL, I get the props I expect - the three above + the missing :account/id and ::fs/config . So why does it work in the repl but not in the component? What is different or how does use-component “mess up” the job its helper has done? This is my component:

(defsc CreationModal [this _props]
  {:use-hooks? true}
  (let [id (tempid/tempid)
        _ (hooks/use-lifecycle #(form/start-form! (comp/any->app this) id AccountForm {:embedded? true}))
        form-props (hooks/use-component (comp/any->app this) AccountForm {:ident [:account/id id]})] ; <-- no :account/id in the props!
    (tap> {:form-props form-props})
    (ui-modal ...))
🙏 🤯

1
tony.kay22:12:32

Some points: • initialize defaults to true on use-component (pretty sure) • If you use an ident that way then use-component closes over it, so the tempid, when rewritten will cause things to break on save • You’re making a new id every render. You would need to hold that constant. • You’re starting the machine only on the first render, which is on the first ID, then use-component is getting a diff ident every time

facepalm 1
tony.kay22:12:14

IMO this kind of thing is just too hard to do well in Fulcro, and I want to make it better. I had not tried this particular case myself (hooks with forms and tempids), so until now didn’t realize how hard this kind of super-dynamic case is. It’s not the kind of code you need often, so perhaps it’s ok that this case is “hard”. There’s a lot of inherent complexity in the problem: form content lifecycle, form component lifecycle, ID management and remapping…

👍 1
tony.kay22:12:21

Not sure it is any easier anywhere else, but because of the tempid problem use-component just won’t work as-written, which is why I turned to a stable component (constant ident) as a parent with a dynamic query.

tony.kay22:12:45

if it makes you feel better, it took me more than half a day to get something working.

tony.kay22:12:41

The tempid remapping problem just requires there be something to track the ident and remapping. Closing over it in use-component is a real problem, because tempid remapping won’t find it there. It is possible to look inside the UISM for the form and extract the ident that way, which would let you pass the id to use-component and might actually fix yours.

tony.kay22:12:52

at which point yours would be a more elegant soln

tony.kay22:12:18

well, almost…the lifecycle thing is a problem. It’s tied to the CreationModal mounting. If the modal unmounts and re-mounts then you’ll lose it. I personally started out in a similar way, but abandoned it when it was flaky…perhaps too soon, since I found that bug in use-component

tony.kay22:12:18

So, IF you are only rendering that component when the modal is supposed to be open, then allocating a tempid once might make this work up until “save”. At which point the memoized tempid is no longer the ID, but won’t be rewritten, and at that point you’d need to pull the ident from the form’s UISM (which you can just do on every render, and figure out when it changes).

👍 1
Jakub Holý (HolyJak)10:12:50

Thanks a lot! I completely forgot I am inside render and creating a new tempid every time facepalm And I have not realized the complexities of the lifecycle w.r.t. start-form and the problem with tempid remapping. > initialize defaults to true on use-component Correct. But I guess it has no effect here since the form has no initial-state (I have tried it in REPL, it returns nil ), > if it makes you feel better, it took me more than half a day to get something working. It does 🙂 I guess my solution could work if I fix the tempid even without proper remapping if I simply close and reset it when the form is saved. Though it will likely require more work to communicate the right entity to the ToOnePicker… Though I now realize that not having a stateful component with a static ident makes using mutations just too complicated…

Jakub Holý (HolyJak)11:12:29

Thanks a lot, Tony! I learned a ton from this and recorded my lessons for posterity in https://blog.jakubholy.net/2022/fulcro-detached-root-component/ I think that my solution without the intermediate static ident is flawed as it has no place to set whether to show the modal or not.