This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2020-01-31
Channels
- # announcements (4)
- # babashka (73)
- # beginners (128)
- # bristol-clojurians (1)
- # calva (8)
- # cider (8)
- # clj-kondo (4)
- # clojars (7)
- # clojure (148)
- # clojure-dev (16)
- # clojure-europe (5)
- # clojure-gamedev (1)
- # clojure-italy (10)
- # clojure-nl (7)
- # clojure-uk (57)
- # clojurescript (57)
- # clojutre (1)
- # community-development (2)
- # cursive (7)
- # data-science (1)
- # datascript (5)
- # datomic (9)
- # events (6)
- # figwheel-main (1)
- # fulcro (91)
- # garden (11)
- # graalvm (14)
- # graphql (1)
- # immutant (4)
- # jobs (1)
- # kaocha (33)
- # off-topic (63)
- # onyx (3)
- # pathom (4)
- # re-frame (23)
- # ring-swagger (1)
- # shadow-cljs (49)
- # sql (6)
- # testing (8)
- # tools-deps (45)
- # vrac (1)
- # xtdb (10)
Thank you for all you do! I signed up for a monthly donation. I wish I could do more.
Hello! I have noticed that if I want to include a component in a router, I must give it a :query
(even if empty) and initial state - if I leave out the former I get a "bad join" exception and if I leave out the latter I get a warning about a component being invoked with nil props. I believed I could use defsc without query/init.state but perhaps I misunderstood?
Yes, dyn routers expect you to pass state through them, so the target must have a query and ident.
It is technically possilble to make that not a requirement, but it currently isn’t written that way
Question: The Element tab in my Fulcro Inspect (1.0.17) is empty. DB etc. work. Is there a way to fix it? Thank you! (Chrome 79 on OSX)
When trying to run fulcro-inspect in Linux I get:
A JavaScript error occurred in the main process
Uncaught Exception:
Error: Cannot find module 'electron-settings'
at Module._resolveFilename (module.js:543:15)
at Function.Module._resolveFilename (/opt/fulcro-inspect-electron/resources/electron.asar/common/reset-search-paths.js:35:12)
at Function.Module._load (module.js:473:25)
at Module.require (module.js:586:17)
at require (internal/module.js:11:18)
at /opt/fulcro-inspect-electron/resources/app.asar/js/background/main.js:2310:741
at Object.<anonymous> (/opt/fulcro-inspect-electron/resources/app.asar/js/background/main.js:5454:3)
at Object.<anonymous> (/opt/fulcro-inspect-electron/resources/app.asar/js/background/main.js:5456:3)
at Module._compile (module.js:642:30)
at Object.Module._extensions..js (module.js:653:10)
not sure why that would be. That module is required for it on all platforms….but I do not test the linux build…you could try building it yourself..the DEVELOPMENT instructions tell you how..it’s easy
I'll try that out then
If it turns out to be a bad build I’ll delete the one from github and try rebuilding it some other time
:thumbsup:
Anyone else has this problem?
How do folks implement Error Boundaries in Fulcro? https://reactjs.org/docs/error-boundaries.html It is annoying to get an empty, white page due to a typo in a (external lib) prop name...
Fulcro components are just regular React components, you simply need to add :getDerivedStateFromError
etc to the options map of defsc
, look at its docstring for arguments.
thank you!
Hey, I've got something I completely don't understand. Suddenly all my revolvers stopped working, every requests gets :com.wsscode.pathom.core/not-found
response
I don't see anything that even changed - do you have any clues how to debug Pathom resolving?
I’d suggest to switch to synchronous versions of parser, reader etc for debugging + add ::p/process-error
to ::p/env
with custom error logging
(defresolver wires-resolver [{:keys [datomic]} _input]
{::pc/output [{:wires [:wire/id]}]}
(let [wires (datomic/q '[:find (pull ?w [:wire/id])
:where [?w :wire/id]]
(datomic/db (:conn datomic)))]
{:wires (map first wires)}))
(def resolvers [connector-resolver connectors-resolver terminal-resolver wire-resolver wires-resolver])
(defn make-pathom-parser
[datomic]
(p/parser {::p/env {::p/reader [p/map-reader
pc/reader2
pc/ident-reader
pc/index-reader]
::pc/mutation-join-globals [:tempids]
:datomic datomic
}
::p/mutate pc/mutate
::p/plugins [(pc/connect-plugin {::pc/register [resolvers/resolvers
mutations/mutations]})
p/error-handler-plugin]}))
user=>
((wires.parser/make-pathom-parser (:datomic system)) {} [{:wires [:wire/id]}])
{:wires :com.wsscode.pathom.core/not-found}
Is there a way in Fulcro or shadow-cljs to show React errors nicely in the page instead of showing an empty page and having to read through the console log? (Without wrapping everything in an Error Boundary.) (E.g. if somewhere in a component I have (dom/div {{:dangerouslySetInnerHTML {:__html "Hi!" }} "I will cause a failure")
? Shadow-cljs shows nicely compile errors but not runtime React errors 😞
There is not currently, nor do I have a strong interest to investigate it..console works fine for me 🙂 …if you have ideas, feel free to share them.
How does fulcro-garden-css work? Is it so that I need to add a :css [[:.myClass ..]]
key with the CSS Garden style definition to the component, which will generate a CSS class with a unique name, which I can obtain via (let [{:keys [myClass]} (css/get-classnames MyComponent)] (div {:classes [myClass]}))
?
Contrary, :css-global
creates the class names as-given and thus there is no need for get-classnames
, right?
(I'd be happy to send a PR improving the docs, I just want to make sure first I actually understand it.)
+ I need to call (com.fulcrologic.fulcro-css.css-injection/upsert-css "componentcss" {:component root/Root})
on my root component and ensure that all components from the Root
down have :css-include [ChildComponent1 ..]
all the way down to the MyComponent
that I want to style with co-located styles. Correct?
as long as components have queries and are linked together, the current version can scan for css at root
Which docstring? I see none on the ns of https://github.com/fulcrologic/fulcro-garden-css/blob/develop/src/main/com/fulcrologic/fulcro_css/css.cljc?
Thank you. I will hopefully contribute some docs changes for idiots like me :)
@U0CKQ19AQ I cannot get the autoscan to work (Fulcro 3.1.8, f-g-css 3.0.7) - I changed to :auto-include? true
:
(cssi/upsert-css "componentcss" {:component root/Root, :auto-include? true})
and removed :css-include [Header]
from my Root
component. Hard reloading and the "componentcss" element is now empty. The Root
and Header
component are connected by queries so autoscan should work?!
Root :query [{:root/header (comp/get-query Header)} ...]
How do you troubleshoot these things? How can I verify that all my components have correct query and are properly linked together?(comp/get-query YourRoot)
should show you the full query of the app (from a CLJS repl)
you can set up deps to use the source of a local checkout of the libraries and add debug statements
Q: According to http://book.fulcrologic.com/#_routing_targets I can leave out :route-segment
for a singleton (";; optional: defaults the the component's ident (singletons only)") yet for this component:
(defsc Private [_ _]
{:query []
:initial-state {}
:ident (fn [] [:component/id :private])}
(div (p "TODO")))
that looks like a singleton to me I am getting
> ERROR [com.fulcrologic.fulcro.routing.dynamic-routing:535] - Route target app.ui.root/Private of router app.ui.root/BaseRouter does not declare a valid :route-segment. Route segments must be non-empty vector that contain only strings and keywords
What am I doing wrong?route segment is always required…there is nothing to make up there…it is a vector of strings I cannot guess, nor does it make sense to
Last question of today: When I copy the code from http://book.fulcrologic.com/#_live_router_example but rename Root
to RootNested
and wrap it in a new Root
, the navigation stops working and gets stuck at "Unknown route". Why? How to fix?
...
(defsc RootNested [this {:root/keys [router]}] ;; former Root
{:query [{:root/router (comp/get-query TopRouter)}]
:initial-state {:root/router {}}}
(dom/div
(dom/button {:onClick #(dr/change-route this ["main"])} "Go to main")
(dom/button {:onClick #(dr/change-route this ["settings"])} "Go to settings")
(dom/button {:onClick #(dr/change-route this ["person" "1"])} "Go to person 1")
(dom/button {:onClick #(dr/change-route this ["person" "2"])} "Go to person 2")
(ui-top-router router)))
(def ui-root-nested (comp/factory RootNested))
(defsc Root [this {}] ;; added
{:query [{:root/nested (comp/get-query RootNested)}]
:initial-state {:root/nested {}}}
(ui-root-nested))
I see, I misunderstood how query works. So I must pass the :root/nested props to the UI-nested-root...
Thanks a lot! I am still only learning...
yep…that’s really the main concept…idents tell Fulcro how to normalize a tree, and queries tell it how to pull data (as that tree) from servers and from the local normalized db…that’s really it. It’s always a tree in the UI, and always normalized in databases. You should always think about the UI as a tree from root (optimizations may jump around, but they rely on the first render to actually be from root)
Since it is normalized in db, you can ask for any subtree from a server and tack it into place.
but the overall tree from root is just that: a data tree from root…just happens to be stored in a normalized form.
the problem was I was kind of thinking in terms of reagent subscriptions and not realizing that query is just info composed to root and the actual data must be propagated from root as in a normal react app.
I understood that…common misconception. It actually would not be hard to make components that could “act” as their own roots and get what you had to work, but the composed queries actually come in handy for so much that it hasn’t been worth the trade-off….routers, for example, use the query to find each other.
Thank you for the helpful error messages such as > You are routing to a router :app.ui.root/BaseRouter whose state was not composed into the app from root. !
I’m trying to make that the norm…still have places that could use improvement, but yeah…
Hm, why do I get ☝️ ? Do I have to query router props in the root component?! I have
Root :query [{:root/content (comp/get-query Content)}]
:initial-state {:root/header {}, :root/content {}}
;-> (ui-content (:root/content props))
Content :query [{:root/router (comp/get-query BaseRouter)}]
:initial-state {:root/router {}}
;-> (ui-base-router (:root/router props))
BaseRouter
But I am passing the state down via props (see the ; -> (ui-..
lines?!
https://github.com/fulcrologic/fulcro-rad-demo/blob/develop/src/shared/com/example/ui.cljc#L74
Every target component of the router has
:initial-state {}, :query []
it really is nothing more than: you provide an initial tree of data that FUlcro normalizes into a database, then it uses the query to pull that state back into the ui
They are not flashed out yet, they will need something eventually (aside the first one which is just info panel)
Hm, now it works suddenly. I did the suggested change then undid it yet it still works. Perhaps it just needed hard reload or something like that...
Thank you, Tony! I learned a lot today!
Hi! Is there a guide to migrate from Fulcro 2 to 3?
Regarding routing, how to make sure that the initial change-route
happens before the application is shown? Currently I do
1. app/set-root!
2. dr/initialize!
3. dr/change-route (based on the current URL)
4. app/mount!
But the app shows first with the default (first) route target and only after a while it switches to the route from 3. http://book.fulcrologic.com/#_initial_route doesn't help here...
@holyjak so change route is a transaction, and transactions go into a queue that is processed soon after. You probably need to put the mount into a timer to allow things to settle down
I should probably formalize a mechanism for initialization that takes care of the timing
the other option is to put a “ready?” flag in your state that hides UI, and then set it to true once you’re sure things are the way you want them
Thank you!
How do I know the transaction has been executed (and thus can mount)?
What I do now is I rely on that transactions are executed sequentially and simply transact! a mutation that does (swap! state assoc :ui/routing-ready? true)
and ask for it in my root component and render nil if false