hello all, I could use this https://github.com/nubank/workspaces lib with Helix. It´s easy
(ns myapp.workspaces.cards
(:require
[helix.core :as hx :refer [$]]
[helix.dom :as d]
[myapp.lib :refer [defnc]]
[nubank.workspaces.core :as ws]
[nubank.workspaces.model :as wsm]
[nubank.workspaces.card-types.react :as ct.react]
[nubank.workspaces.card-types.test :as ct.test]))
(defnc Painel []
(d/div {:style {:color "blue"}} "This is a testing"))
(ws/defcard hello-card
(ct.react/react-card
($ Painel)))
easier than using devcards 🙂
worspaces == devcards?
also, is it worth trying helix without shadow-cljs? with the new clj tooling?
you have to use the figwheel branch to do that, but otherwise it works fine :)
@ashnur we used vanilla Clojurescript with helix, and now using hx with the figwheel branch
I am confused now : ) but do I deduce it correctly that everything should work with everything ?
btw, we talk so much about performance but so far I've seen two attempts to actually measure this, one the benchmark a week ago, and one my attempts with sierpinski triangles and both failed to materialize the said improvements. : )
helix gives you more tools than other react wrappers to optimize
that’s all
could I ask help with my sierpinski attempt sometimes in the future? I don't want to sound entitled, I realize our goals might not match up 🙂
sure! if you post a repository I can review it when I have time
I’ve also tried to setup helix’s defaults to be relatively good for performance, but maybe I’ve done it wrong
I expect most of my personal struggles at the moment to come from simply inexperience with clojurescript, so that's also why I don't want to say anything more than just that I, personally, struggle a bit 🙂
the repo contains html code for the original demo from here https://claudiopro.github.io/react-fiber-vs-stack-demo/
the code that uses the old react fiber release works flawlessly, my first attempt fails very badly 😞
so much so that my first viceral reaction was to do it in js first using latest Fiber because I just can't believe I can fail this much, but that's silly of course, it's very easy to fail at it if you don't understand the language : )
yeah definitely. there’s a lot to learn.
that demo is using a very old version of React Fiber, too, so it’s not a 1:1 translation
possibly, but the code is very simple 🙂
What I had the most struggle with is the createRoot method, it kept losing the root
Discovered a strange behavior today. Using helix.experimental.refresh
, I get different refresh behavior with a component depending on whether it calls a hook with clojure's #
syntax, vs. (fn [x] ...)
syntax. In other words, (let [f #(my-hook %)] (f foo))
has a different refresh behavior from (let [f (fn [x] (my-hook x))] (f foo))
.
looking at the compiled output, it looks identical except the refresh signature function gets called with a string like "(my-hook p1__121991#)"
instead of "(my-hook x)"
. Could hte presence of a "#"
in the signature string be doing something?
what is the latest version of helix I could try? should I clone the repository for this? I've been using 0.0.10 for a while and it seems everyone else uses something else 🙂
@ashnur i'm using 0.0.10
cool, good to know, i am reading the docs now, i left out everything that sounded scary at the first time
like experimental
: D
At least you won't lose your job for using them...
yeah, I want to do the sierpinski thing now, that's not for work 🙂
@aiba what’s the difference in behavior?
my best guess is that the #()
syntax might generate a new symbol name every refresh, which would cause a new signature to be created and invalidate your component’s state
in other words, it’s not the #
in the signature; the name before the #
might be changing each render
but also, I would be very careful that you are following the rules of hooks: https://reactjs.org/docs/hooks-rules.html
calling a hook in an anonymous function makes my spider senses tingle that you might be doing something dynamic in a way that could easily break due to violating the rules
a good rule of thumb is to follow the naming convention set by React/helix: always start your custom hook name with use
, e.g. use-my-app-state
difference in behavior: with the "#" symbol in the signature, the entire component gets re-rendered even when state should be unchanged.
that's a good theory (symbol name changing on refresh), i can test that by looking at the compiled code
@lilactown you are absolutely correct, the name of the symbol was changing upon refresh!
and yeah, admittedly it's a little sketchy to build functional indirection on the hook calls, but i think i'm OK in my case. there is a static vector of constants, and i'm mapping a hook over the vector, so the order/count of hooks should be preserved.
regarding naming custom hooks with use-, i did see that helix analyzer specifically checks for (string/starts-with? (name x) "use-")
and i was wondering if that would miss direct calls to react/useState
or calls to third-party js librarys that name their hooks useFoo
it might yeah
it should check for camelCase or kebab-case, I just haven’t gotten around to writing that regex 😛
we don’t use react-refresh at work yet so it’s something that I only experiment with in my free time
gotchya, well i use it every day with helix and it kicks ass!
so thank you 🙂
happy to write the expression and send a PR for camel case if you'd like
I would appreciate that!
it's 1 line if we take a dependency on https://clj-commons.org/camel-snake-kebab/
otherwise a multiline check
I would prefer not to take a dependency
ok, sounds good
if you have any ideas how to handle the anonymous function, let me know
we could canonicalize signature strings by renaming the variables in the expressions, but that could be a slippery slope of trying to compare two expressions and determining whether they are in some sense equivalent
im actually OK just remembering not to call hooks from within #
anonymous functions
hopefully it's valid to (mapv use-foo some-constant-vector)
because that i do all the time
and seems to be working so far
well, if you turn on {:helix/features {:check-invalid-hooks-usage true}}
it will definitely throw compiler warnings 😉
gotchya, i haven't done that yet
what’s your use case for doing that?
there is some kind of hook checking built in to react native at least. sometimes it gives me warnings about hooks.
one example is there's a navigation screen with a bottom tab that has ~5 buttons, and the tabs are statically configured, and i want a hook for each tab.
just make sure that you never want to conditionally render one of the buttons 🙂
I would write out each usage of the hook personally. more typing, less potential bugs / have to remember it’s okay to call hooks in a loop just this once
of course it’s up to you. the :check-invalid-hooks-usage
linter will annoy you about it
I guess I should add some way to disable it for certain exprs…
yeah, it's a tradeoff. the downside with writing each hook separately is that it makes it easier to add a tab but forgot to hook it, which is a different kind of bug
this way, the code says all tabs are hooked