This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2024-03-20
Channels
- # announcements (5)
- # aws (15)
- # babashka (12)
- # beginners (87)
- # calva (13)
- # cider (16)
- # clj-kondo (4)
- # clojure (22)
- # clojure-argentina (1)
- # clojure-europe (9)
- # clojure-houston (1)
- # clojure-nl (2)
- # clojure-norway (25)
- # clojure-uk (5)
- # clojurescript (12)
- # core-typed (37)
- # cursive (15)
- # datomic (40)
- # editors (8)
- # emacs (4)
- # events (1)
- # hyperfiddle (29)
- # keechma (8)
- # leiningen (6)
- # lsp (7)
- # malli (25)
- # off-topic (26)
- # pathom (10)
- # portal (3)
- # re-frame (22)
- # reitit (1)
- # releases (1)
- # ring (2)
- # shadow-cljs (18)
- # yamlscript (1)
I’m using an atom client side to contain a paginated list of items. When it loads, it contains 10 items on page 1. When the user navigates to page 2, 10 more items are loaded and added, and so on. This means that were they to go back to page 1, those 10 items are available immediately. This is conditional of a category selection. So all items loaded are in a specific category. This means that if the user switches category, the cache atom now contains all items from the previous category, plus 10 new items. It’s a side effect of being stateful, and a classic and major downside of doing it this way. What happens currently is that all items not belonging to the current category is cleared out of the atom on switch, and this works. In React, the same problem would probably be solved by giving the root component a key based on the current category, which would cause React to tear down the current state and rebuild it, thus effectively masking the statefulness happening in it. Not that I want to use it, but is there a mechanism like this in Electric? Can you make an arbitrary tree conditional on some hash?
for-by can be wrapped i.e. put a single child branch in a collection size 1 and manage it with a key
i also needed this at least once, maybe it should be made public api
Ah, that’s clever. It feels like something one shouldn’t make a habit out of. But for clearing out e.g. states holding settings etc. that specifically controls views, and doesn’t really rely on data streamed from the DB etc., it could be an acceptable pattern to reset to defaults reliably.
An attempt:
(defmacro given
[key & body]
`(first (e/for-by identity [_k# [~key]]
~@body)))
(given something
(dom/div (dom/text "Hello"))
(e/on-unmount #(println "Torn down")))
Not sure would it should be called. But theoretically then, given a change in something
, “Torn down” should be printed though there are no dependencies.
This works as expected. I ended up rewriting it as,
(defmacro while
"Given a truthy `key`, executes the reactive `body`.
`body` re-executes for each distinct value of `key`."
[key & body]
`(first (e/for-by identity [k# [~key]] (when k# ~@body))))
It’s semantically tenuous, but clojure.core/while
felt like the closest thing to map the behavior to.Thanks! I guess it’s more Dustin’s while
than mine though, since he suggested the core mechanic.
It’s interesting, for example
(e/defn TestWhile
[]
(e/client
(let [!a (atom 10)
a (e/watch !a)]
(while (and (pos? a) a)
(println "Hello")
(swap! !a dec)))))
If this while
is cljs.core/while
, this prints “Hello” ~100 times and then crashes the app.
If it is the while
above, it prints “Hello” 10 times and then stops, with no crash.
It makes sense why the core while
crashes the app, but incidentally the bespoke while
exhibits behavior closer to how while
works outside of Electric.what is the crash from core/while?
agree it's not surprising, but it still might be a bug that it throws NPE (though certainly the behavior isn't defined)
Very cool. I think that the name while
doesn't quite capture the idea: the important functionality this provides is to remount the body when the key changes.
I suggest perhaps distinguishing
I've created an https://github.com/milelo/electric-multi-client-app, a minimal Electric Clojure app based on https://github.com/hyperfiddle/electric-starter-app providing a server with multiple independent clients, routing and an https://v1-docs.xtdb.com/guides/in-a-box/ database. Each client has its own dependencies and electric reactor.
How should I go about securing my Electric routes while exposing some public routes on the same server?
In the starter app template, the recommended place to inject (wrap-authentication)
like basic auth is in electric-websocket-middleware
, which fires before anything else, returning 401 for all routes.
Is it possible to add auth middleware only to Electric websocket upgrades?
Have you considered using an if statement at the top of your electric app?
I want to exclude auth from some non-Electric routes, e.g. /api/do-thing, and /public-thing.html
Otherwise I would do it all in Electric
Deploying two different apps on two different domains or ports is an option, but then I have to deploy two things.
Oh ok, that seems like a ring question, surely it is possible, i would find the ring support channels and ask there
yeah I guess my question becomes: can I safely move the electric websocket detection to later in the middleware pipeline, or will content-type stuff mess with it?
If you search my messages I should have posted examples on this. In my case electric app lives in /app
and authenticated and rest of the routes are unauthenticated.
You could secure it externally (for free) through https://www.cloudflare.com/en-gb/products/tunnel/