A small field report on Reagami. I am experimenting a bit with a combination of Reagami, Scittle and Replicant on the backend. Trying to get a setup like Datastar. I have something basic working, but I wanted to share one issue others might also run into with Reagami at some point. I was rendering on the html body like
(reagami/render js/document.body [my-component])
And this works mostly fine, except if there are other processes injecting html as well. In my case a password manager injecting some element, this triggers an incorrect children count (https://github.com/borkdude/reagami/blob/main/src/reagami/core.cljc#L242) and causes the full dom to reload. And therefore also emptying forms and such. After I figured this out, I fixed it by using the variant mentioned in the README. So a div#app as a first child of the body
(reagami/render (js/document.querySelector "#app") [my-component])
Now things work very nicely!Nice!
Why are you using reagami when you already have replicant?
I'm using replicant on the backend. It generates the hiccup send via an SSE stream to the browser which is loaded with Reagami
I am using Replicant on the backend instead of hiccup or something else because I am using replicant-kanban as a test case
that's great. but scittle also supports replicant on the front-end. of course I'm happy you are trying reagami, but in scittle it's interpreted right? if this is fast enough, than it's a really nice demo :)
Yeah it works like the normal replicant-kanban. I can see some benefits of a datastar way of working. So no need to compile clojurescript this way and the backend as a source of truth. I have a set of local actions such a dragging etc defined with Scittle, and the rest is posted to the backend. This triggers an event in the stream and re-rendering
in scittle it's interpreted right?Ah yeah, so I added Reagami to my custom Scittle build, but to debug why Reagami was fully re-rendering I loaded it from source with some debugging in it. Didn't notice a difference in speed
It was a small change to Scittle. If you are interested I can do a PR for sci.configs and a scittle plugin as well
sure!
Also cool to see live updates in multiple browsers with replicant-kanban btw
do you think reagami has a bug in this respect or not?
I think it just expects to not mess with the dom nodes it created itself. but you can create child nodes which it leaves intact with :on-mount
Not a bug, but maybe if someone mounts on the body a warning could be helpful. If this becomes a common problem i guess
Probably people would not notice until they are using forms etc. Until then they might experience some slowness in Re-rendering i guess
I'm not exactly clear on the issue. Could you describe the issue from the start?
sure, here or on github?
here
Ok, so when I mount my app on the body element:
(reagami/render js/document.body hiccup)
Reagami is in trouble because in my browser my password manager happens to inject an element in the body. This changes the children count in Reagami and this triggers a render a the root.
I've added these debugging lnes in the Reagami code:
if (not (== old-children-count new-children-count))
(do (println "Old count vs new count" old-children-count new-children-count)
(js/console.log "Replacing Children" old-children)
(.apply parent.replaceChildren parent (.map new-children #(create-node % root))))
....
Then I see the below in the console, regardless of what elements actually changed. So the patching is not efficient because of this and things with a state like forms (and I'm guessing components) also get reloaded
Choosing a different element then the body might be a good way to avoid conflicts caused by html injection by third parties
(reagami/render (js/document.querySelector "#app") hiccup)
Is that clear enough or still a bit vague?
yes, this is an expected problem. reagami keeps track of all the nodes it created with a vdom like architecture. when you mess with the dom manually, it will get confused.
if you want to inject dom nodes, you can do with :on-render or :on-mount etc. indeed it's better to mount on a child node in the body specially dedicated to your app. it's not a problem reagami can fix. Probably other libs like this like replicant will also have the same problem (I expect..)
Yeah in this case I wasn't aware of the injection and at first it didn't seem to be a problem. Only when I was wondering why the form was being reset
so the scenario is likely: body has 0 children. reagami does it's job, inserts 1 (the app?) then password manager comes along, injects another dom element. on the re-render, reagami compares the amount of children in the vdom (1) with the new one (1 from the app). but the real dom node count is two... if the password injects before your app, reagami will replace your password stuff with the app
could this be the scenario?
if so, I think we could fix this with id reconciliation
if the password manager inserts after the app node, then I think there won't be any problem
Sorry, I got interrupted. Yeah I think that's the scenario