fulcro

Book: http://book.fulcrologic.com, Community Resources: https://fulcro-community.github.io/, RAD book at http://book.fulcrologic.com/RAD.html
genekim 2020-11-22T07:34:20.249700Z

@tony.kay I’m loving using Guardrails, and I know precisely the feeling that triggers me bringing it into a project — when I find docstrings or function arguments that no longer make sense to me, weeks or months after I wrote that code. 🙂 Thanks for your great work here! I’m looking for help on something happened to me today — it’s actually something that happened using Ghostwheel, too. I added Guardrails to the project, and started using the >defn forms with no problems (and Guardrails forms were recognized by Cursive)I but then later found that arguments weren’t being checked. Is there a checklist to confirm that Guardrails is working properly? I have :jvm-opts ["-Dguardrails.enabled"] in my deps.edn I ran this form, which was accepted:

(>defn tt
  [x] [int? => string?]
  (+ 1 1))
But this form ran, without an error:
(tt "abc")
=> 2
(I expected passing in a string to result in an error…). Any tips? Thank you, all!

Jakub Holý 2020-11-22T22:26:04.264500Z

I don't really know but I believe that the default behavior in Q might be to only log warnings and you must switch on throwing exceptions.

tony.kay 2020-11-23T16:13:10.268300Z

Check your (System/getProperty "guardrails.enabled") and make sure it is actually set in your REPL

tony.kay 2020-11-23T16:13:41.268700Z

There’s very little to the macro, other than the config + turning it on/off

genekim 2020-11-24T02:33:46.275200Z

Hmm!! Okay, that was super helpful!! Obviously, I don’t understand :jvm-opts as well as I thought! 🙂 > (System/getProperty “guardrails.enabled”) > => nil Huh. I just spent 30m scouring the docs on deps.edn…. Is it not allowed to put a :jvm-opts at the highest level in a deps.edn file?

{:src      ["src"]
 :jvm-opts ["-Dguardrails.enabled=true"]
 :deps     {analytij/analytij                   {:mvn/version "0.4.0"}
            com.fulcrologic/guardrails          {:mvn/version "0.0.12"}
            org.clojure/data.csv                {:mvn/version "0.1.4"}
            vlaaad/reveal                       {:mvn/version "1.1.164"}}
 :aliases  {:test {:extra-paths ["test"]
                   :extra-deps  {lambdaisland/kaocha {:mvn/version "1.0.700"}
                                 org.clojure/test.check {:mvn/version "1.1.0"}}}}
THANK YOU!

genekim 2020-11-24T02:36:06.275400Z

…holy cow… :jvm-opts must be inside of an alias.. 😱 https://clojure.org/reference/deps_and_cli Prepare JVM environment JVM arguments may either be passed on the command line (with `-J`) or by using data stored in an alias under `:jvm-opts` and passed with `-X` or `-A` or `-M`

genekim 2020-11-24T02:39:06.275600Z

It’s working. Thank goodness. (Trying not to weep at the time I spent on this…. Worth it, though! 🙂

genekim 2020-11-24T05:01:43.275800Z

@tony.kay BTW, can one put things like #(instance? LocalDateTime %) (or String or any class) into the parameter types? When I try, I get this error. Thx for your great work here, and I’m looking forward to your commercial offering — consider me on the “must buy” list, as well as happy to test anything you have!

(>defn tt2
    [x] [int? => #(instance? java.time.LocalTime %)]
    (+ 1 1)))
Syntax error compiling at (src/analytics/guardrails_test.clj:10:1).
Unable to resolve symbol: fn* in this context

tony.kay 2020-11-25T02:00:29.284500Z

yep…parsing limitation. Might fix eventually, but for now just s/def that and use the keyword instead

genekim 2020-11-27T22:05:12.002Z

Thank you! Makes total sense now! And PS: just watched your RAD video on YouTube, after listening to your interviews on ClojureScript podcast and scanning all the docs. Wow. I'm inspired to give it a try this weekend!

genekim 2020-11-27T22:06:16.003500Z

Thanks for all your great work — Fulcro RAD seems like the closest we've come to Microsoft Access for designing form based apps. That's meant as a huge compliment!!! Keep up all your amazing work!

genekim 2020-11-22T07:34:57.250400Z

(And there is an empty {} guardrails.edn file in my project directory…)

genekim 2020-11-22T07:38:50.251100Z

(I’m using Clojure Version: 1.10.1.727, java/11.0.5-fx-zulu)

2020-11-22T15:23:42.259700Z

I'm having trouble getting a delete mutation to work when I enable a remote on the mutation. I'm trying to delete [:foo/id 1] using the following code:

(defsc Foo [this {:foo/keys [id text] :as props}]
  {:query [:foo/id :foo/text]
   :ident :foo/id}
  (div
    {:onClick #(comp/transact! this [(m/delete-foo)])}
    "foo: " id " text: " text))

(def ui-foo (comp/factory Foo {:keyfn :foo/id}))

(defsc Root [this {:keys [foo]}]
  {:query [{:foo (comp/get-query Foo)}]
   :initial-state {}}
  (div
    (div "foo stuff")
    (when foo
      (div (ui-foo foo)))))
(defmutation delete-foo
  [_]
  (action [{:keys [state]}]
    (swap! state update :foo/id dissoc 1))
  (remote [env] true))
;; resolvers.clj
(def foo-table
  (atom
   {1 {:foo/id 1 :foo/text "testing foo"}}))

(pc/defresolver foos-resolver [env input]
  {::pc/output [{:foo [:foo/id :foo/text]}]}
  {:foo (get @foo-table 1)})

;; mutations.clj
(pc/defmutation delete-foo [env input]
  {::pc/sym `delete-foo}
  (log/info "Deleting :foo/id 1 from foo-table")
  (swap! foo-table dissoc 1))
(defn ^:export init []
  (app/mount! app ui/Root "app")
  (df/load! app :foo ui/Foo)
  (js/console.log "Loaded"))
With the remote enabled, the resulting app state looks like this (instead of :foo/id {} which is what I expect):
:foo/id {1 nil}
And after doing some searching, it looks like the issue is being caused by this: https://github.com/fulcrologic/fulcro/blob/4a9f28f9099bfae7028a28d42fa9a8a3f1d33aa9/src/main/com/fulcrologic/fulcro/mutations.cljc#L98 After the client mutation deletes [:foo/id 1], at root I have :foo/id {} . So far so good. But... when the update-errors-on-ui-component! function runs, it finds no remote-error?, and uses update-in s ref dissoc k, resulting in the following:
core.cljs:198 #p ref => [:foo/id 1]
core.cljs:198 #p (:foo/id s) => {}
core.cljs:198 #p (remote-error? (:result env)) => false
core.cljs:198 #p k => :com.fulcrologic.fulcro.mutations/mutation-error
core.cljs:198 #p (:foo/id (clojure.core/deref state)) => {1 nil}
Is this a bug or have I missed some portion of the documentation that explains it? Maybe some of my assumptions are wrong? I'm new to Fulcro so I must assume it's not a bug - it's an old function. I just can't understand how to fix it -- or if it needs fixing at all 🤕

tony.kay 2020-11-23T16:20:13.269400Z

1. You can choose to delete from a parent. Then the “component” won’t be the one you’re deleting. 2. You can change the default result action. It is pluggable. Take out the errors on ui component stuff, perhaps you don’t even use it. 3. You can choose not to GC this particular thing…there’s a lot of RAM in a browser

cjmurphy 2020-11-24T08:10:28.276100Z

One thing that strikes me is your global resolver is liable to return {:foo nil}. You could slightly alter things so that if (get @foo-table 1) is nil then your resolver actually returns say :unknown-foo. I regard any resolver returning nil as a bug in my own code.

2020-11-25T00:21:42.282Z

That's a good rule of thumb to remember, no resolver should ever return nil. Thank you guys. It ended up being a silly fault of my own but your replies were helpful nonetheless.

Helins 2020-11-22T20:25:50.264300Z

Buggy input range behavior I cannot quite reproduce, hence seeking opinion. It seems that modifying both the max value and the value itself at the same time when rendering prevents the value from being updated in the DOM. Has this happened to you before? I am logging both props at rendering and in componentDidUpdate , I am absolutely sure that both are correct and inspecting the DOM shows the max value changing as expected but not the value. After a few hours of hair pulling, my simple hack is to keep max at 1 and deal with value as a percentage of the real value in my data, but the core problem is very troubling.

tony.kay 2020-11-23T16:16:07.268900Z

are both in the query? All components come with a shouldCopmonentUpdate that checks for props diffs. If props don’t change, components don’t re-render…and if things are not in the actual query, then targeted refresh will not send them (and thus nothing will change). If rendering is broken, this is almost always the cause.

Helins 2020-11-24T13:24:17.276400Z

They are, I even println them in the rendering function to make sure that all values used for rendering are indeed what they should be. Still, when a mutation leads to changing both max and value at the same time, only max gets updated in the DOM although I know for a fact value changed as well (ie. its prop). Furthermore, If I save my files and trigger compiler + re-rendering, then value gets updated as expected. Well, to be more precise, I noticed some float wizardry. value doesn't stay exactly the same, it's changing from 1.444446 to 1.4444457 for instance. No idea what is happening there! Disclaimer, that component is not exactly trivial, it uses getDerivedStateFromProps for instance, there is room for a weirdness. However I did spend some time on it, trying different variations, the end result was always the same. I was wondering if it wasn't due to React, maybe something like the algorithm updating max before value? But I would have a hard time believing no one noticed this before.

tony.kay 2020-11-25T01:59:58.284300Z

If you get to a small reproducible issue that I can pull into a workspace card it would be helpful. I don’t have the time to do much else. I’m not aware of any Fulcro issues, but I’m sure getDerivedStateFromProps is not heavily used.

Helins 2020-12-03T12:29:38.046100Z

@tony.kay All right, the problem kept reappearing... and the solution is weird. I have no idea why but working with float values (even set as strings, as they should) results in the DOM input range updating its value only every couple of times, and this happens only with renders happening after mutations, not after set-state!. The rendering function runs all right, everything is fine, all props are correct, it really is about the DOM (React itself?) and the value (other DOM properties such as max were always updating as expected). The issue completely disappeared since I've starting working exclusively with integers. Spooky. If you hear about this again someday I recommend mentioning it in the book since it is a particularly strong head-scratcher (hours spent on the matter...)

Jakub Holý 2020-11-22T22:26:04.264500Z

I don't really know but I believe that the default behavior in Q might be to only log warnings and you must switch on throwing exceptions.

okeydoke 2020-11-22T23:33:54.267200Z

Is there something special you have to do to get child components to render from an imported react component library? I’ve been banging my head against a wall for ages now and not sure what I’m doing wrong. This is what I’ve got at the moment and not sure why only the app container component is being render? Very new to clojure and fulcro and not sure whats wrong.

(def ui-app-container (interop/react-factory libComp/AppContainer))
(def ui-header (interop/react-factory libComp/Header))
(defsc Root [this props]
  (ui-app-container (ui-header)))