Set-submitting does not work for reagent
mitchellandwebb opened this issue · comments
I've defined the form like this (approximately):
(defn my-form []
[{:keys [values
handle-change
handle-submit
submitting?
form-id
]}]
(let [name "name"
email "email"
message "message"
]
[:form { :on-submit handle-submit
:id form-id
}
[:div {:class "ContactPage-NameGroup"}
[:label {:for name} "Name"]
[:input {:type "text", :id name, :name name
:on-change handle-change
:value (values name)
}]
]
[:button {:type "submit"
:disabled submitting?
}
"Submit"
]
])
)
(defn form []
[f/form { :prevent-default? true
:clean-on-unmount? true
:path :contact-form
:on-submit (fn [{:keys [state path values dirty reset]}]
(f/set-submitting state path true))
}
my-form
])
When I click the submit button, I get an error in the console that says there's no protocol IAssociative defined for reagent's Ratom.
I've looked at the source code fork/reagent.cljs
, and it looks like the the error is coming from my call to set-submitting
. I'm passing in state
, but that state is a Ratom that gets passed to core/set-submitting
, which attempts to add a key to the ratom, which obviously doesn't work.
In the re-frame version, it looks like you pass db
, which is specific to reframe? If so, how would I get the set-submitting
to work with reagent, so I can make the submit button disabled while submitting?
Looked at it further, and I changed my :on-submit
function to
:on-submit (fn [{:keys [state path values dirty reset]}]
(swap! state #(assoc-in % [path :submitting?] true))
)
This fixed the issue in my code, but I would hazard that a fix still needs to be made in fork
.
Hello! I should definitely update the README to clarify the behaviour of set-waiting
, set-submitting
and set-server-message
.
As you already figured out, they do not perform the swap!
operation for you. The idea behind it is that all the state changes should be sent together when possible, therefore triggering only one re-render.
To explain this in an example, let's assume that set-submitting
can take an atom and perform the swap!
operation:
:on-submit (fn [{:keys [state path values dirty reset]}]
(f/set-submitting state path true))
If my use case requires me to do something else with the state besides setting submitting, then I would end up with:
:on-submit (fn [{:keys [state path values dirty reset]}]
(f/set-submitting state path true)
(swap! state update ...))
As you can see, swap!
is being called inside set-submitting
and by my custom logic, which is not ideal. Contrarily, with the current behaviour of set-submitting
you can easily do everything in one swap!
like this:
:on-submit (fn [{:keys [state path values dirty reset]}]
(swap! state #(-> %
(f/set-submitting path true)
(update :some-key inc))))
Also, note that if you only need to perform the set-submitting
operation, you can simply pass the function to the atom like this:
(swap! state f/set-submitting path true)
Hope this explanation helps :)
Yes, please update the documentation, because the Reframe example doesn't seem to know about atoms.
But that helps a lot, thanks!