This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2018-01-02
Channels
- # adventofcode (2)
- # bangalore-clj (1)
- # beginners (26)
- # boot (7)
- # cider (21)
- # clara (45)
- # cljs-dev (1)
- # cljsrn (2)
- # clojure (168)
- # clojure-berlin (1)
- # clojure-india (4)
- # clojure-italy (7)
- # clojure-nl (1)
- # clojure-russia (1)
- # clojure-spec (10)
- # clojure-uk (12)
- # clojurescript (31)
- # datascript (2)
- # datomic (28)
- # defnpodcast (9)
- # emacs (2)
- # events (4)
- # fulcro (193)
- # hoplon (127)
- # hypercrud (1)
- # jobs (1)
- # jobs-discuss (38)
- # keechma (1)
- # luminus (5)
- # off-topic (16)
- # onyx (4)
- # parinfer (9)
- # portkey (2)
- # portland-or (1)
- # precept (5)
- # re-frame (9)
- # reagent (8)
- # remote-jobs (7)
- # rum (3)
- # shadow-cljs (2)
- # spacemacs (19)
- # specter (2)
- # testing (1)
- # unrepl (34)
@tpliliang Your question is kind of difficult to understand. I think maybe you’re saying you have something from a database you’d like to use as the data model for a dropdown?
@levitanong I’m not sure I’d worry about it. Even the link you gave says: “You can avoid this by defining the ref callback as a bound method on the class, but note that it shouldn’t matter in most cases.”
you could save the bound function as an attribute on the instance, then it would be the same thing every time (for that instance)
@tony.kay Haha, I’ve actually run into a weird infinite loop with it. It seems to rerun when fulcro rerenders the component. My workaround was to add a guard to check if the ref is nil, but I think this points to a deeper issue. how would one save it as an attribute on the instance?
@levitanong if you are wondering where to do that, I can think on 2 places: 1. on initLocalState
. 2. part of a custom factory method
on any of those places, you can try to use (gobj/set this "someHandler" (fn []))
I was thinking this is like a constructor, so a component might be mounted and umounted many times, but it's only constructed once
but for the purpose of ref
, it only matters at all in the context of render. mount/umount will call it again anyhow so it doesn’t matter
but in practice it shouldn't make much a difference I guess
yeah, all of then should work fine 🙂
I just don’t remember if the this
in componentWillMount
is the same thing that you get once it is mounted
I think that's correct, but have to try
thanks for the help, guys!
no problem
worked like a charm, guys! thanks again. 😄
cool, which hook point you used to save the handler?
componentWIllMount. seemed like least effort to me
fair enough 🙂
@levitanong Thanks for letting us know
@levitanong so, I assume what you wrote is a lot more code that a simple anon function. What’s your reasoning? I’m curious because I just started tinkering with the card to see what it would take to make that work well, and it is a lot more confusing, a lot more code, and the only thing it seems to save is an extra call to a function that probably takes microseconds to run.
Curiosity :P it wasn't actually a lot more code because the anon function contained a check on the presence of an extant reference. Without it, I was getting a blown stack.
hm why does forms init-form overwrite existing values with their defaults?
it didn't used to
nope init-form
hm...
Well I'm printing out a specific entity
and I can distinctly see a boolean being flipped
it isn’t a lot of code…https://github.com/fulcrologic/fulcro/blob/develop/src/main/fulcro/ui/forms.cljc#L621
basically init-one
and init-many
call back to init-form*
, which in turn checks for the form state key
I'll try to isolate the thing
but it does walk the whole form set, so a subform, for example, would get initialized if it were not already
well I have a value in a subform position already
an entity with no form control data yet
yes I understand initializing the form control, but why flip the existing boolean data on subform entity to default
ah, I see. You’re saying it should be initializing the form control data, but it is affecting the entity state
not sure what you mean by that
(defn f [state-atom]
(swap! state-atom ...))
(defn g [state-atom]
(swap! state-atom f))
My functions work with state, not state atom
I'll make a new project and see if I can replicate
I've had a couple of things misteriously break after migrating to 2.0
the reason I made the guess I made is that perhaps you have one stage that is making a change, and then something is reverting it by accident. A nested swap is a common way to accidentally cause that
admittedly my form/modal mutations and components are complicated as hell
so I'll try to find a nice example
OK, so that could be a serious indicator of a problem with something internal to Fulcro…Very interested in knowing about regressions
No. My mutation was -> sequence of normal function operating on state
and then I interposed
print statements
and I noticed that the boolean flips when init-form fn is called
the fn, not the mutation
So, is the field you’re talking about a form field of the subform that was not yet initialized?
I'm working on making a new project that will demonstrate that
If I am able to demonstrate that
I still suspect I'm screwing it up somewhere
ok, so, init-form does make sure your entity has values on all fields that are declared
yes the issue is with a boolean field(checkbox) that has initial value of false
default in form is true
so init-form overrides it to true
maybe you are using an if to check if a prop is nil, but if also works on false same as nil
the false/nil duality is quite a tricky thing
easy fix, and I had test coverage that tested multiple types…just not boolean 😕 Lesson learned on testing Clojure…boolean is the most important type to test 🙂
then I have a much trickier bug (or possibly my mistake) -> sometimes transactions break my router and the props don't get passed down to the :current-route component
I used inspect to look at the thing
the only other change in that release right now is the rendering refactor that eliminates the need for react-key
. Let me know if you see rendering weirdness
and db is fine, my root component and router props is fine, but the component that my router points to has empty props. But that only changes when I do a transaction, the initial load is fine.
And it doesn't happen just with a particular transaction.
I'll probably need to make an example of that one, since it happens on some transactions but not on other
so, I would be interested in hearing what happens if you try 2.1.0-SNAPSHOT with an option change on that: Pass {:render-mode :keyframe}
as :reconciler-options
to your new client.
what's that for?
rendering initial frame is done from root. Refresh (on transactions by default) are done from the component using an ident query. I’d be interested in seeing if that changes it.
otherwise with the latest version there's quite a bit of flickering when using bootstrap Collapse
I have a panel with 10 items in it, then 10 more items in a collapse, when I expand the collapse, the items outside of it flicker, (transaction target is the panel enclosing both groups), and it didn't happen in 1.0
I'll try the keyframe render now
So, rendering in 2.0 is nearly a complete rewrite from Om Next. Are you doing anything (via timeouts) while the collapse is happening?
but I see the collapse fires a bunch of timeouts with swaps in them
it will cause extra renders, but they should be no-ops that are short-circuited by React
I would suspect that flicker is caused by unstable keys causing react to throw away DOM and re-insert it
I use them where I get warnings
Om Next always did render from root on such swaps…so there should be no difference there
Usually ID of the entity, but sometimes if I don't have that, I use a keyword if a single entity, or index of the element in the sequence
ok, that should be stable. Flicker would indicate a react unmount/mount. The only reason it would do that is if:
1. Your state temporarily changed so that the linkage made them disappear, then changed back to make them appear
2. The :key
of a parent (even root) changes. That will cause the entire subtree at that key to unmount/remount
We use this “trick” with react-key
at root to force a re-render of the app on locale changes.
So, put log messages in your :componentWillMount
lifecycle in a few strategic spots and see if you can see umount/mounts
it's gotta be number 1
because I added print sentence into ident function of the whole panel that contains the collapse
and it shows that opening the collapse
ident gets called 8 times
4 times with normal props
2 times with empty props
then 2 times with normal props
so, not sure what you’re doing exactly, but empty props coming to ident can be bad…probably mean you’re rendering something in a parent even though it isn’t there.
rendering a missing thing could cause unstable keys if the keys are based on the props
like I said
that is probably related to that problem I mentioned earlier
after some mutations I get empty props on components directly under a router
I put print into the render. Opening the collapse it gets called 3 times. Empty props, then twice with normal props
I tried using inspect to figure out what's wrong
but DB is fine and root props are fine, but the component directly under the router sometimes gets empty props
I have
(route/defrouter MainRouter :main-router
(ident [this props] [(:ui/component-id props) :singleton])
:people People
then in component People I have.
[this {:keys [ui/component-id ui/collapse people/all-people]}]
{:query [:ui/component-id {:people/all-people (fp/get-query Person)} {:ui/collapse (fp/get-query b/Collapse)}]
:ident [:ui-components/by-id :ui/component-id]
right but all children have idents [:ui-components/by-id x]
but why does it work on inital render
:keyframe
will “fix” that, and 1.x would have worked with it as long as you didn’t try to normalize things with it.
it’s just broken in several ways…you happened to find a way to make it “seem to work ”
I am using keyframe and I still have the "occasionally empty props" problem
but I will fix the ident
yeah, fix the ident….that will clear up your problems. drop the keyframe. It is really just for curiosity and isolating possible bugs
oh yeah, this fixed everything
thanks a lot
dropped the keyframe and it works
lovely
UI refresh is optimized by running ident-based queries to refresh sub-trees. If your ident is wrong, things won’t work well. In 1.x, the rendering used the path from root to optimize render. in 2.x we rely only on idents for refresh. This is much simpler internally, but will expose broken ident functions.
Speaking of idents, do they have to be a pair of keywords? What if I have a component that represents a link between two entities
an ident is always a keyword first, the second element can be anything that supports equality comparison
The only reason you’d have such a component is if it has some representation beyond the linkage (such as abstracting the linkage into a higher-level concept)
Router is a perfect example. It is a thing whose “state” is an ident. (current-route)
it also mixes in a union, so it can select which query to use to continue down the graph efficiently…