This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2018-06-26
Channels
- # adventofcode (2)
- # beginners (69)
- # boot (37)
- # cider (6)
- # clara (31)
- # cljs-dev (75)
- # cljsrn (5)
- # clojure (72)
- # clojure-dev (7)
- # clojure-italy (11)
- # clojure-nl (8)
- # clojure-russia (2)
- # clojure-spec (56)
- # clojure-uk (54)
- # clojure-za (1)
- # clojurescript (156)
- # cursive (2)
- # datomic (34)
- # emacs (1)
- # fulcro (227)
- # hoplon (74)
- # jobs (1)
- # jobs-discuss (16)
- # leiningen (5)
- # lumo (17)
- # off-topic (9)
- # om (3)
- # onyx (10)
- # other-languages (1)
- # portkey (2)
- # re-frame (2)
- # reagent (36)
- # reitit (1)
- # remote-jobs (1)
- # ring-swagger (8)
- # shadow-cljs (85)
- # slack-help (2)
- # spacemacs (6)
- # specter (3)
- # sql (17)
- # test-check (15)
- # tools-deps (80)
@tony.kay Are there any plans to add a graphql network layer in fulcro ? đ Thinking of people that would like to have something like Apollo client in clojurescript.
@claudiu you can use pathom for that đ
the documentation still missing, but it has support for GraphQL integration
@wilkerlucio Yep. Was just looking at that đ But was thinking having that extra step (no mention in the fulcro docs) might make a lot of people view fulcro as only a "full-stack" library, and not a prime-candidate if they already have a graphql backend and just want to use fulcro on the client side.
yeah, it's mostly a documentation problem at this point, but pathom still need some extra work to make it easier to use, the current setup is cumbersome, but I'm working on some things to make that easier
I just have been very very busy lately, but I'll get there đ
will help a lot when pathom provides some http drivers, setting those is the major pain point now
sounds really cool. Haven't tried it, but looking at the EDNâGraphQL
seems like there is a good chance that it could work really nice with graphql on the backend, without to many compromises.
yeah, I had to remove from the docs because they got outdated, but there was an example on how to connect directly with the Github GraphQL API, and also how to mix that with other graphql endpoints or rest, you can mix and match everything there
@claudiu Pathom is the official answer for Fulcro in all things query processing/parsing
Somebody mentioned that fulcro seems to full-stack and not a good fit for current projects. The docs cover restfull api, but could not find anything to share about fulcro + graphql.
Was thinking about apollo, and that fulcro is pretty much the closest thing in clojurescript. If it would work out of the box with graphql that would be pretty amazing.
Weâre working towards that, but Wilker and I are both pretty busy at the moment. I understand that it is a critical use-case.
probably the most criticalâŚbut also somewhat time consuming in terms of documentationâŚ.which as Wilker says, is the majority of the remaining work.
@claudiu FWIW fulcro has a backend story, but it's not required at all, you can implement your own remote on the frontend and make it work with whatever you want
i used fulcro with an existing rails backend and it worked well
I think his point is more that people are looking for GraphQL, and we can do it well, but there is no doc/example
@tony.kay Yep. Referring to tweets like this https://twitter.com/lilactown_/status/995132059734556672 . Can see how if you have an existing graphql backend could be easy to miss the point that fulcro can do it really well.
Started rebuilding my personal project in fulcro, but the more I think about it it would make more sense to have the backend in graphql than fulcro server. No complaints about datomic pull syntax for the workflow... But graphql is the "standard", and I could expose that to clients also, plenty of docs & big websites that have graphql public api.... Doubt any third party clients would bother learning & using my edn public api.
ah i see
yeah does seem like of all the cljs react frameworks, fulcro is in the best position to take advantage of GraphQL
i'm having more confusion about parent components not getting re-rendered, even though I'm using keyframe mode now
i've got this router:
(defrouter ProfileShowRouter :profile-show-router
(fn [this props] [:profile/by-id (:profile/id props)])
:profile/by-id Profile)
and a mutation that triggers it to change:
(m/defmutation show-profile-id [{:keys [profile-id]}]
(action [{:keys [state] :as env}]
(swap! state (fn [s]
(-> s
(fs/add-form-config* Profile [:profile/by-id profile-id]))))
(r/route-to-impl! env {:handler :profile-show
:route-params {:profile-id profile-id}})))
There is a child component of Profile that is supposed to be about to trigger a route to another profile (ie profiles can have links to one another)
When I click the link, I can see in the database that the router updates to the correct profile id. And the fields passed down to the child component that triggered the mutation get updated.
But the fields on the Profile component itself don't change, as if the query didn't get rerun when the route happened
I'm not sure what I'm missing, why the router changing wouldn't trigger a refresh of all its child components , since the id of the profile has changed
Any advice for how to troubleshoot this kind of issue? Or maybe I'm going about the whole thing with the wrong approach
@chrisjswanson if you have keyframe mode on then every component on the screen should re-render, unless their props have not changed
that's what i thought - so it means my props must not be changing for the component in question
yes that would be my guess, should confirm that first
do you have fulcro inspect installed?
using the element tab, try to inspect the component that contains the router
ok let me try that, one sec
since that contains the props that ultimately go to the Profile component
if that doesn't work you can always fall back to good old js/console.log
đ
cool, i didn't even realize that element inspector exists
very helpful
so the ident is not changing
yeah that was all @wilkerlucio, he's a beast
well he has me appreciation đ
also, FYI i think the inspector is a great example application if you want to learn how to write fulcro apps
so if the app db changed when i triggered the mutation, but the component ident didn't change, i must have something wrong with my router definition i guess?
ok, good advice, i'll have to look at the code
(for the inspector)
the way that i'm using the router to swap by entity id - is that an intended usage?
in the docs, it looks more like it's being used to switch between panels with fixed labels
the book does have an example of using the router with ids like the way you are doing it
you can see the live example (with source) at the end of that section
personally i typically use the routers for fixed labels and handle ids internally
ok, yea i did read through that - it was the example that i used to build what i'm trying to fix at the moment.. just making sure i understood the usage correctly
yea that's what i was wondering, if it's more common to just deal with ids yourself
cause i also wasn't sure what the router passes to initial-state fn when it creates the component its routing to
i believe the router just passes some initial-state data that makes it's first key-value pair the default tab
hm i see
so if I have a router like the one i pasted above, and i route to update the id of the entity its showing , it should trigger that entity to update its ident and re-run its queries, right?
Initial state is passed through the router, as long as you composed the initial state of the router to root
Yes, is the answer, but if you only have one Screen, a router is possibly overkillâŚunless you are using it to just get routing tree support
The router is largely about minimizing query among multiple kinds of screens. If youâre just switching between data for the same screen, the router is just extra weight since an ident alone will do
I see. Yea, i was using it in a routing tree, so i could switch a top level panel and then show the correct profile id.
And that is actually working fine - going from "list" view to "details" view is ok. It's when I click a link to switch from one "details" view to another "details" view that I'm running into issues
Namely, it seems, that the ident didn't actually change when I routed (well it changed in app db , but not in the routed component)
what does routing tree support mean?
it's so i can issue a route name and have it be a set of route commands that update nested routers
ah got it
to ensure the top level router is showing the page that contains the sub-router which will select entity id
@tony.kay is there an advantage to using ids inside routers? vs just handling them on my own via queries and such?
If I were to do it that way, I'd basically just have an entry in app db for "selected-profile" or something along those lines, and my component would query for that, right?
yeah that's what i was thinking
though i guess doing ids with a router does make things less ad hoc
So it is fine to use IDs in routers, and the routing tree has :param/x support to fill them in
It is possible, Chris, that there is a bug in keyframe mode đ Iâm not aware of it being used much by ppl, as it is a relatively new feature.
as i'm exploring more, it seems possible
but Iâm pretty sure it worksâŚ.so if youâre seeing the data update to the correct values, and not seeing it in the UI, Iâd wonder if either (1) you didnât enable it correctly or (2) it has a problem.
Try adding a follow-on read of the join key of your router at the top and see if it fixes it
yea, i did try follow-on of :root/top-router
you have hot-reloading code setup for dev right? doesn't that trigger a root re-render also?
no luck unfortunately
i do have hot code reloading - could try to trigger it that way
i'm wondering if we should have a force-root-render button in the inspector?
yea, i did it here:
(defn ^:export init []
(reset! app (fc/new-fulcro-client
:reconciler-options {:shared {::i18n/message-formatter message-format}
:shared-fn ::i18n/current-locale
:render-mode :keyframe}
:started-callback (fn [app]
(df/load app :profiles/all Profile
{:target [:list :profile :profile-list :profile-list/profiles]}))))
(start))
how can i get a reconciler to pass to force-root-render?
yea, so not even force-root-render seems to be working
but when i use fulcro-inspect to see the element, the data is different that what the ui is showing
to see the router? The router itself should have stateâŚalso, your target of load looks wrong to me
i'm looking at the router's target, the "Profile" component
what do you mean by "target of load" ?
oh i see
that target is too deep, and would not be targeted in the normalized component, which you may be mis-reading as ârightâ when in fact it is wrong
ok, it seemed something wasn't right about that
could i just show you the whole app somehow? it's just a page, a small app for learning
ok thanks, appreciate it
@chrisjswanson i'll take a look too, i'm curious and might be able to help
awesome , appreciate the help
hopefully i didn't do anything too boneheaded đ
hopefully you did, that easier to debug đ
haha true
i'll take a look in little in a bit, just need to finish some emails real quick
sure, no rush, i'm around all afternoon
so the problem is when you click a specific profile it doesn't open?
yea, the idea is it's like an address book, and a person can have emergency contacts
i want the emergency contact to be a button to link to the other contact page
what's really strange is that the subcomponent which shows the emergency contact info DOES get updated , but the rest of the profile data remains the same in the ui
even though, upon inspecting it in fulcro inspector, it seems the component has the right data
let's take this chat out of the main channel
@currentoor It might be useful to post the final resolution to the channelâŚppl might be interested
figured it out đ
yep, so the resolution:
turns out it was nothing related to state, routers, or data it a react DOM thing lol
@tony.kay Chris will post a little blurb about it
I was using an input component with a defaultValue on it, but it didn't have a key param
yep , no bug đ
so the behavior that i got was that the first time the component gets displayed, everything works correctly (because defaultValue gets used when it's first shown)
but when I changed things, the props came through correctly to the component, but the input value didn't get updated. React ignored the new props, because the input's key hadn't changed
in order to make it work correctly, i needed to supply a key that included a prop that I knew would change (ie the new entity id i'd routed to). that guarantees react updates the input when the route happens and the component props change
big thanks to @currentoor for not just fixing the bug but helping me understand why it wasn't working, and teaching me some useful debugging tricks đ
happy to help
FWIW @chrisjswanson you should still try to figure out why you get those random nils in your appstate
I'd bet money that they will bite you in the butt later...
consider making devcards for your components, helps isolate issues IMO
That doesnât sound quite rightâŚif props change it updates. The key does not have to change. Key is only a bug if there are adjacent children with the same keyâŚ.changing keys, however, will force react to re-render the component.
@tony.kay he was using :defaultValue
had it been :value
it would have updated regardless
he was using :defaultValue
because using :value
would result in that flicker bug where the cursor jumps to the end of the input value
i know this more of a react thing but maybe we should have some explicit docs about inputs and tricks like using :defaultValue
and :key
in the book
@tony.kay do you recommend using routers for modals?
semantic ui makes it easy not to
Ah, so cursor jumping to the end is a different thing, and that should be already handled by Fulcroâs wrapped inputs. Should not see that unless you use a js ecosystem thing
@chrisjswanson I think you were having cursor jumping problems if your keys were UNSTABLE
that would cause the input to unmount and remount. You should definitely use :value
, and should not end up seeing cursor jumping
(unless your keys are unstable, in which case the unmount/mount will happen and cause you headaches)
@currentoor Iâm not aware of a :defaultValue
:key
trick to handle cursor jumpingâŚnot sure what you mean
using :defaultValue
and :onBlur
for inputs so you don't have mutations for every keystroke
@tony.kay I'm using fulcrologic/semantic-ui-wrapper
you are correct - the built-in fulcro dom/input doesn't have the cursor jumping issue
the "defaultValue trick" that I'm using is to set the defaultValue of the component instead of the value , and then use onChange event to update its value in the app db. that way the input component's text value and the app db stay in sync , even though it's not a controlled input
i wasn't using an unstable key; in fact I wasn't specifying a key at all . i did go back and try replacing "defaultValue" with "value" once I set the key , but alas the cursor jump bug returned
So, I guess thatâs okâŚcontrolled inputs in semantic UI donât tolerate the async updateâŚthey expect you to use component-local state for your control, which is screwy IMO
but technically thatâs what you have to do with ârawâ inputs in react in general
Fulcro works around that itself by wrapping all inputs in a way that tracks the changes in local state for you, so they are âsemi-controlledâ
do you think the same technique could be applied to the semantic-ui-wrapper ?
it does seem a little weird to have to use defaultValue
In fact, I havenât tried this, but I think you might be able to just use the wrap-form-element
in dom.cljs as long as the control in question uses :value
âŚworth a try
i could give it a shot. i'm still pretty new to react, may be over my head. but if i can make it work, would you want the pr?
interesting, i'll give that a try too
Yeah, let me know how that goesâŚyouâll need to require the Semantic UI control via require, then pass that class to that function. Itâll return you a function that acts like a new factory for that control
@chrisjswanson are you using shadow-cljs?
still trying to get it to work
are you using sui-factory?
or get-sui
(ns app
(:require ["semantic-ui-react/dist/es/index.js" :refer [Input]]))
...
(def sui-input (dom/wrap-form-element Input))
(sui-input {:value v :onChange ...})
Also: note that a LOT of react-semantic-ui wrappers do nothing more than emit DOM with a few classes. In those cases I strongly recommend just using dom and making your own little wrappers. That way you donât have this headache, and SSR can work in the future for you if you need it.
Even the active controls donât have complicated logic. I ended up writing logic for some of them myself on my own project, just because I got tired of things like this
so just use dom to emit the correct elements with the semantic ui classes on them and it'll mostly work the same?
I should probably update the fulcro semantic ui wrappers to say that, and deprecate it
ok, that makes sense
when you get to dropdowns, modals, and such: those have logicâŚbut itâs simple usually
were you able to add label or anything to that sui-input ? it worked for me (gave me a blank input), but it doesn't seem to take other params
and it just plays around with classes. I made my own autocomplete based on SUI dropdownâŚbut their logic wasnât working the way I wanted. Most of the work is in the CSS tweaking IMO, so I just wrote the logic myself. I had spent 2 days trying to make js ecosystem ones work the way I wanted. It took me 4 hours to make my own with their CSSâŚlesson learned
yep you are right, #js
good point, i probably couldn't made my own with dom in the time i spent fiddling around trying to fix that cursor jump bug
no problem, really appreciate the advice
in my experience I end up using MUCH less time making my ownâŚesp for the ones that donât have complex behaviorsâŚeven the autocomplete one with load went much better when I just rolled my own
yea, maybe in time there could be a fulcro native ui widget library
and you can âfixâ the #js
bit with:
(let [factory (dom/wrap-form-element Input)]
(defn sui-input [props] (factory (clj->js props)))
oh cool, nice đ
In time Iâd prefer someone else maintain the CSS, so using semantic UI CSS, and having the logic coded in fulcro for the dynamic components would be nice.
I want to be able to leverage the js ecosystemâŚso much out there, but so far Iâm about 50/50 on sucessfully finding stuff worth using.
right.. yea that is a hard tradeoff
and a lot of (non-input) stuff in SUI works, but then anytime you render with external js SSR gets harder
cause new users will want batteries-included, and we can't recreate everything. but some stuff is just a waste of time and it should be rebuilt natively
I think everyone writing js struggles with the same crapâŚthe ecosystem just has a lot of stuff that doesnât quite work the way youâd like it to
yea i ran into the ssr thing as soon as i started using SUI - had to add cljs tags all over the place, eventually just gave up on ssr
Iâm working on a project, and Iâm using SUI, but I decided against using most of the react js for itâŚin cases where it is useful I write CLJC stubs that on the CLJ side can render a âreasonableâ version of it via DOM, since SSR is usually just for initial load anyhow
tbh i never even learned js , except what's been required to get my cljs working
yea that makes sense , seems like a logical approach
and I use the HTML Converter in the Fulcro Book to convert samples from the Semantic UI website to Fulcro DOM đ
haha cool đ
just inspect the page, play with the control, copy the elements, paste them in the converterâŚboom
even âactiveâ controls are easy to write, since you can see what CSS has to change over time that way
i'm definitely gonna give that a try too , seems like it could sidestep a lot of headaches
@chrisjswanson I just updated the fulcro wrappers to 2.0.0-beta2, and I added this wrapping in by default for the controls I found that took :value
to make a controlled component
was an easy enough fix, and I didnât realize it was doing the cursor jump thingâŚso thisâll make everyoneâs experience better đ
The only caveat to this âfixâ is that if you hook up an onChange and donât make it a controlled component, then you donât really end up with a controlled component đ This wrapping âassumesâ that when you set an onChange, youâre going to make your state match that of the input.
I just took that pattern and added it to the wrappers: https://github.com/fulcrologic/semantic-ui-wrapper/blob/develop/src/main/fulcrologic/semantic_ui/factories.cljs#L15