Fork me on GitHub
#clojurescript
<
2023-06-07
>
Mark Wardle07:06:00

Hi all, What's the best way of sharing initialisation state with a front-end component? I have a cljs front-end [using re-frame, but I don't think that matters] talking to a server backend using Pathom queries. I want to simplify the application structure recognising that most of my user interface can actually be rendered server-side. Therefore, I want to only sprinkle a bit of cljs into some components of some pages. I can pass some state through the URL itself, and let my cljs component(s) query for anything else [e.g. what should be listed in pop-ups/drop-downs etc], but is there an alternative to sharing initial state with a component used like this?

Mark Wardle08:06:23

So the options as I see it are: • Only use URL and fetch other data as required • Put state into the rendered page using script tags, much like one would pass a CSRF token for POSTs • Do some kind of client side hydration so that any other state is just passed down the component chain client side in the same way as it was rendered server side. Am I missing a better way? The second option sounds messy for more complex data than a simple token.

thheller09:06:19

I use https://github.com/thheller/shadow-graft a lot (I made it), so I guess thats number 2 on your list

👍 2
👀 2
Mark Wardle09:06:20

You’re a star. Thank you very much!

Lidor Cohen08:06:39

Hello 🙂 Does anyone knows the reason why protocol methods doesn't conform to the general (fn) args destructuring? It interest me because it happens to prevents them from being variadic which is a more serious design offense (IMHO) than breaking the api to function's args so I expect the reason behind that to be very important.

thheller11:06:43

imho its not needed and easily replaced with something that moves the "destructuring" code elsewhere

(defprotocol TheThing
  (-the-actual-fn [this x]))

(defn the-fn [this bar & args]
  (-the-actual-fn this (convert-args bar args)))

thheller11:06:55

not uncommon to wrap protocol methods like that

thheller11:06:52

as to why I have no clue, I'm guessing there are solid reasons.

Lidor Cohen12:06:55

can you do that with IFn -invoke?

thheller12:06:22

IFn already has support for varargs via apply

Lidor Cohen13:06:39

IFn support varargs? Are you sure? This is from core.cljs:

(defprotocol IFn
  "Protocol for adding the ability to invoke an object as a function.
  For example, a vector can also be used to look up a value:
  ([1 2 3 4] 1) => 2"
  (-invoke
    [this]
    [this a]
    [this a b]
    [this a b c]
    [this a b c d]
    [this a b c d e]
    [this a b c d e f]
    [this a b c d e f g]
    [this a b c d e f g h]
    [this a b c d e f g h i]
    [this a b c d e f g h i j]
    [this a b c d e f g h i j k]
    [this a b c d e f g h i j k l]
    [this a b c d e f g h i j k l m]
    [this a b c d e f g h i j k l m n]
    [this a b c d e f g h i j k l m n o]
    [this a b c d e f g h i j k l m n o p]
    [this a b c d e f g h i j k l m n o p q]
    [this a b c d e f g h i j k l m n o p q r]
    [this a b c d e f g h i j k l m n o p q r s]
    [this a b c d e f g h i j k l m n o p q r s t]
    [this a b c d e f g h i j k l m n o p q r s t rest]))
Why would there be so much signatures? And how can I pass varargs to -invoke?

thheller13:06:29

well its not strictly varargs but the compiler turns invocations with more arguments into the last where rest is the seq of remaining args

thheller13:06:56

so it can be called as if it had varargs

Alex Miller (Clojure team)13:06:24

The origins of this are in protocols providing a straight line to what’s available in the jvm

Alex Miller (Clojure team)13:06:34

And then cljs copying clj

Alex Miller (Clojure team)13:06:43

Or maybe I am not fully understanding the question

Lidor Cohen13:06:57

@U05224H0W, I wasn't aware of that piece of magic... is it a special case for IFn? or does it apply to all protocols? i.e after passing 20 args I get the rest as seq @U064X3EF3 You seem to have answered the question 🙂 Can you elaborate a bit about the straight line to jvm or is it too much details?

Lidor Cohen13:06:58

@U05224H0W I get invalid arity 😞

; Execution error (Error) at (<cljs repl>:1).
; Invalid arity: 22

Alex Miller (Clojure team)13:06:53

I think maybe I misdiagnosed

thheller14:06:36

and yes, this is a special case for IFn. other protocols can use the defn indirection.

Lidor Cohen14:06:28

About the code: I'll post it later but it's just a random implementation of IFn invoke longest signature. About the defn wrap, I think you are missing the cost of that wrap. Protocols which actually need to support varargs take a great penalty for that wrappers because it means the standard entry point (the function the protocol defines) no longer correct and there's another (random) entry point. It actually means that you must define your protocol in means of vec / seq args and the syntactic enrty point separately. And if you realize it a bit later then you must break api (not the case if varargs were supported). Not to mention this breaks the api of how you work with fn args (protocol method is by all means fn). I think the aggregation of all of the above is not something to dismiss...

Lidor Cohen14:06:43

@U064X3EF3 thank you for taking the time to answer my question

Grigory Shepelev14:06:59

Hi, all! 👋 How can I get channel's buffer size in clojurescript? In clojure it would be https://danielcompton.net/snippets/core-async-channel-size

(.n (.buf ch))
But clojurescript won't allow this.

Grigory Shepelev14:06:55

of course picard-facepalm

(.-n (.-buf ch))

p-himik15:06:43

I suspect this is also a proper syntax for CLJ.

Grigory Shepelev15:06:44

This is the only proper syntax for cljs. Note the «-»

p-himik15:06:39

I know. I'm saying that (.-buf ch) is also a proper syntax for CLJ. While (.buf ch) might work, it's not something you commonly see in the wild. .x is generally for calling member functions and .-x is for accessing properties.

Arthur Fücher16:06:33

Is there any library to generate static websites? with the html content, not just an empty html with js injection like Next.js or Gatsby.js does

seancorfield18:06:54

Do you mean like a static site generator (command-line) tool? Or are you looking specifically for a library you can use from ClojureScript to do that on the fly?

hifumi12318:06:10

You can use Hiccup and macchiato-core to have a Ring server rendering fully static sites in CLJS. But at that point, why not use Clojure? The JVM can handle much more than Node.js in terms of load, and it offers much better debugging and introspection capabilities.

hifumi12318:06:42

I see little advantage to using Node.js for a static site, and with JVM Clojure you'll also have access to libraries like Selmer, which offer Django-style templates, in case you don't like Hiccup.

wojciech19:06:02

I think the point is to avoid backend processes altogether (be it Node of JVM). Clojure(Script) for nice developer experience, but rendering to simple HTML + CSS for performance on both server and client (like Astro in JS world). (Unfortunately I don't know the answer here)

Arthur Fücher19:06:08

I think that this is what I want: "Do you mean like a static site generator (command-line) tool?" To give more context, I'm using reagent and it generates a static site. But, it generate an empty index.html with a javascript . Since my site does not have nothing dynamically, I just want something that can take advantage of reusing components, but without making all those things with js in the end.

isak19:06:20

I haven't looked into it, but I would check out the 'Static Site Generation' section of this website: https://www.clojure-toolbox.com/

seancorfield19:06:56

> To give more context, I'm using reagent and it generates a static site. But, it generate an empty index.html with a javascript . This is expected: ClojureScript compiles down to JavaScript so the "static site" is rendered at runtime via JavaScript. Command-line static site generators typically work from Markdown sources and don't have "reus[able] components" in the way that Reagent etc do -- so perhaps you can elaborate on what sort of static site you're trying to produce and what those components would be?

hifumi12320:06:17

@U04HQGN8QCV Again, the best option IMO is to just use Hiccup. You can do so from JVM Clojure, or CLJS, or probably even babashka. But I would personally just use the JVM since it'd give access to the most Clojure libraries specifically for your purpose (websites generated entirely on server side), and JVM in production gives me way less headaches than Node.js in production

👍 4
hifumi12320:06:26

While Hiccup on its own doesnt have a notion of components like reagent does, you can still create functions returning hiccup and simply call them within a larger "component".

Arthur Fücher13:06:57

My concern with using pure html/js without react or something like this, is to loose some features like local state. But could be an option, for small applications. I'll try it