Fork me on GitHub
#hyperfiddle
<
2023-03-10
>
nivekuil02:03:27

trying to bind hyperfiddle.electric-client/*ws-server-url* , but it seems missionary doesn't preserve dynamic bindings when it retries the connection in boot-with-retry?

2
Dustin Getz02:03:59

you’re losing a custom binding on reconnect?

nivekuil02:03:23

yeah. and when it does connect I get this error in browser console:

_LT_x is undefined

 in (try ...) 

 TypeError: _LT_x is undefined
    with runtime.cljc:601
    iterator Continuous.cljs:144
    missionary$impl$Continuous$suspend missionary.impl.Continuous.js:487
    missionary$impl$Fiber$Fiber$swich$arity$2 Continuous.cljs:16
    missionary$core$switch core.cljc:165
    hyperfiddle$electric$impl$runtime$variable_$_cr159841_block_3 runtime.cljc:619
    result impl.cljc:60
core.cljs:3953:14
    cljs$core$IFn$_invoke$arity$5 core.cljs:3953
    cljs$core$IFn$_invoke$arity$4 core.cljs:3948
    cljs$core$IFn$_invoke$arity$3 core.cljs:3942
    cljs$core$IFn$_invoke$arity$2 core.cljs:3936
    cljs$core$IFn$_invoke$arity$2 core.cljs:3971
    G__160034__delegate runtime.cljc:86
    G__160034 hyperfiddle.electric.impl.runtime.js:71
    1 Latest.cljs:34
    missionary$impl$Latest$transfer missionary.impl.Latest.js:148
    cljs$core$IDeref$_deref$arity$1 Latest.cljs:10
    cljs$core$_deref core.cljs:688
    cljs$core$deref core.cljs:1477
    1 Latest.cljs:28
    missionary$impl$Latest$transfer missionary.impl.Latest.js:148
    cljs$core$IDeref$_deref$arity$1 Latest.cljs:10
    cljs$core$_deref core.cljs:688
    cljs$core$deref core.cljs:1477
    1 Latest.cljs:28
    missionary$impl$Latest$transfer missionary.impl.Latest.js:148
    cljs$core$IDeref$_deref$arity$1 Latest.cljs:10
    cljs$core$_deref core.cljs:688
    cljs$core$deref core.cljs:1477
    1 Latest.cljs:28
    missionary$impl$Latest$transfer missionary.impl.Latest.js:148
    cljs$core$IDeref$_deref$arity$1 Latest.cljs:10
    cljs$core$_deref core.cljs:688
    cljs$core$deref core.cljs:1477
    1 Latest.cljs:28
    missionary$impl$Latest$transfer missionary.impl.Latest.js:148
    cljs$core$IDeref$_deref$arity$1 Latest.cljs:10
    cljs$core$_deref core.cljs:688
    cljs$core$deref core.cljs:1477
    cljs$core$IDeref$_deref$arity$1 runtime.cljc:547
    cljs$core$_deref core.cljs:688
    cljs$core$deref core.cljs:1477
    hyperfiddle$electric$impl$yield2$transfer_loop yield2.cljc:30
    hyperfiddle$electric$impl$yield2$transfer_recover yield2.cljc:31
    out yield2.cljc:37
    hyperfiddle$electric$impl$yield2$transfer_input hyperfiddle.electric.impl.yield2.js:231
    hyperfiddle$electric$impl$yield2$transfer yield2.cljc:42
    cljs$core$IDeref$_deref$arity$1 yield2.cljc:13
    cljs$core$_deref core.cljs:688
    cljs$core$deref core.cljs:1477
    value Continuous.cljs:179
    missionary$impl$Continuous$push missionary.impl.Continuous.js:565
    missionary$impl$Fiber$Fiber$unpark$arity$1 Continuous.cljs:18
    missionary$core$unpark core.cljc:172
    hyperfiddle$electric$impl$runtime$variable_$_cr159841_block_4 runtime.cljc:619
    result impl.cljc:60
    G__159181__0 cloroutine.impl.js:45
    r Continuous.cljs:74
    missionary$impl$Continuous$step missionary.impl.Continuous.js:321
    1 Continuous.cljs:205
    missionary$impl$Continuous$transfer missionary.impl.Continuous.js:614
    cljs$core$IDeref$_deref$arity$1 Continuous.cljs:12
    cljs$core$_deref core.cljs:688
    cljs$core$deref core.cljs:1477
    missionary$impl$Reactor$pull Reactor.cljs:87
    missionary$impl$Reactor$sample Reactor.cljs:98
    value Reactor.cljs:258
    missionary$impl$Reactor$push missionary.impl.Reactor.js:768
    cljs$core$IDeref$_deref$arity$1 Reactor.cljs:16
    cljs$core$_deref core.cljs:688
    cljs$core$deref core.cljs:1477
    1 Latest.cljs:28
    missionary$impl$Latest$transfer missionary.impl.Latest.js:148
    cljs$core$IDeref$_deref$arity$1 Latest.cljs:10
    cljs$core$_deref core.cljs:688
    cljs$core$deref core.cljs:1477
    1 Latest.cljs:28
    missionary$impl$Latest$transfer missionary.impl.Latest.js:148
    cljs$core$IDeref$_deref$arity$1 Latest.cljs:10
    cljs$core$_deref core.cljs:688
    cljs$core$deref core.cljs:1477
    1 Latest.cljs:28
    missionary$impl$Latest$transfer missionary.impl.Latest.js:148
    cljs$core$IDeref$_deref$arity$1 Latest.cljs:10
    cljs$core$_deref core.cljs:688
    cljs$core$deref core.cljs:1477
    missionary$impl$Reactor$pull Reactor.cljs:87
    missionary$impl$Reactor$touch Reactor.cljs:120
    missionary$impl$Reactor$publish Reactor.cljs:347
    missionary$core$stream_BANG_ core.cljc:885
    _rec__3 runtime.cljc:786
    iterator Reactor.cljs:341
    missionary$impl$Reactor$publish missionary.impl.Reactor.js:1064
    missionary$core$stream_BANG_ core.cljc:885
    _rec__3 runtime.cljc:779
    cljs$core$IDeref$_deref$arity$1 Reactor.cljs:312
    cljs$core$_deref core.cljs:688
    cljs$core$deref core.cljs:1477
    missionary$impl$Reactor$pull Reactor.cljs:87
    missionary$impl$Reactor$sample Reactor.cljs:98
    missionary$impl$Reactor$touch Reactor.cljs:123
    missionary$impl$Reactor$propagate Reactor.cljs:137
    missionary$impl$Reactor$event Reactor.cljs:281
    missionary$impl$Reactor$run Reactor.cljs:316
    reactor_call core.cljc:870
    iterator Ambiguous.cljs:320
    missionary$impl$Ambiguous$suspend missionary.impl.Ambiguous.js:910
    missionary$impl$Fiber$Fiber$park$arity$2 Ambiguous.cljs:16
    missionary$core$park core.cljc:162
    cr112668_place_22 electric_client.cljs:108
    result impl.cljc:60
    G__159181__0 cloroutine.impl.js:45
    x Ambiguous.cljs:262
    missionary$impl$Ambiguous$ready missionary.impl.Ambiguous.js:689
    missionary$impl$Ambiguous$boot Ambiguous.cljs:28
    G__159181__2 impl.cljc:64
    missionary$impl$Ambiguous$backtrack Ambiguous.cljs:34
    missionary$impl$Ambiguous$branch Ambiguous.cljs:73
    missionary$impl$Ambiguous$ready Ambiguous.cljs:307
    missionary$impl$Ambiguous$boot Ambiguous.cljs:28
    missionary$impl$Ambiguous$run Ambiguous.cljs:358
    missionary$core$ap_run core.cljc:178
    G__159181__3 impl.cljc:65
    G__52817__2 core.cljs:4358
    iterator Ambiguous.cljs:320
    missionary$impl$Ambiguous$suspend missionary.impl.Ambiguous.js:910
    missionary$impl$Fiber$Fiber$fork$arity$3 Ambiguous.cljs:18
    missionary$core$fork core.cljc:169
    hyperfiddle$electric_client$send_all_$_cr112559_block_0 electric_client.cljs:65
    result impl.cljc:60
    G__159181__0 cloroutine.impl.js:45
    x Ambiguous.cljs:262
    missionary$impl$Ambiguous$ready missionary.impl.Ambiguous.js:689
    missionary$impl$Ambiguous$boot Ambiguous.cljs:28
    missionary$impl$Ambiguous$run Ambiguous.cljs:358
    missionary$core$ap_run core.cljc:178
    G__159181__3 impl.cljc:65
    G__52817__2 core.cljs:4358
    input Reduce.cljs:36
    missionary$impl$Reduce$run missionary.impl.Reduce.js:128
    2 core.cljc:524
    missionary$impl$race_join/j.cancel[index_157112]< impl.cljs:179
    missionary$impl$race_join missionary.impl.js:613
    variadic core.cljc:115
    c_156678 Sequential.cljs:29
    missionary$impl$Sequential$suspend missionary.impl.Sequential.js:134
    missionary$impl$Fiber$Fiber$park$arity$2 Sequential.cljs:13
    missionary$core$park core.cljc:162
    hyperfiddle$electric_client$connector_$_cr112581_block_3 electric_client.cljs:74
    result impl.cljc:60
    G__159181__0 cloroutine.impl.js:45
    x_156679 Sequential.cljs:40
    missionary$impl$Sequential$step missionary.impl.Sequential.js:151
    resume Sequential.cljs:53
    onopen electric_client.cljs:32

nivekuil02:03:13

for context, i'm writing a use-electric react hook

👀 2
Dustin Getz02:03:05

can you send me a gist of what you have? it can be sloppy

Dustin Getz02:03:21

i’m headed to bed but we will look tomorrow

Dustin Getz02:03:01

ok, i see how you’re setting the binding, i need to read the src, don’t remember how it works, we will get back to you

nivekuil02:03:23

thanks, also for further context I need to override the endpoint because I'm just using the provided jetty server alongside my existing http server. But I also think it'd be really cool to spin up electric instances dynamically

nivekuil02:03:26

I want to use electric more surgically for latency-critical multiplayer use cases and have a bunch of electric clients embedded in react

Dustin Getz16:03:16

@U797MAJ8M this snippet works the first time, it is only reconnect that loses the dynamic?

Dustin Getz16:03:15

which makes sense, ok

Dustin Getz16:03:21

If I am not mistaken, you can (set! ws-server-url ...) at top level

Dustin Getz16:03:24

Upon review of the history I think I do consider this a bug, we should capture the binding set at boot, though we are unlikely to fix it soon unless you can't get it to work

nivekuil21:03:09

cool, I can connect so that's not an immediate problem. The error I get after that is weird though. It looks like runtime/with is scheduled in a callback, and when it's fired the second arity <x is undefined?

👀 2
nivekuil21:03:18

this stuff is really opaque to troubleshoot

Dustin Getz22:03:32

i dont understand, was there progress or did i send bad guidance

Dustin Getz22:03:26

and are you saying the binding is intermittently available? sometimes it reconnects?

Dustin Getz22:03:34

i think maybe i need to clone your repo

nivekuil22:03:51

I'm referring to the stacktrace I sent above

nivekuil22:03:57

should make a separate thread maybe

nivekuil22:03:19

but after it connects, nothing is happening except for that error in the console

Dustin Getz22:03:07

i've desynced from you, can you state the issue from the beginning without referring to any prior context

Dustin Getz17:09:46

Are you still customizing ws-server-url in this way?

nivekuil20:09:18

@U09K620SG it looks like I just did (set! hyperfiddle.electric-client/*ws-server-url* "") , but I think that isn't good enough for something like a per-component endpoint

👀 2
xificurC09:03:14

there's ui/select which is used in the https://github.com/hyperfiddle/electric/blob/b5a86efe63d456131cb5fd953ee6f8ae9e029427/src-docs/user/demo_virtual_scroll.cljc#L67. We did not wrap radio pickers yet since using the typeahead and select was fine for our use cases. Your w3schools example would be built in electric

(dom/form
  (dom/input (dom/props {:type "radio" ...

Can12:03:47

Okay thank you so much and I am sorry my repo clone is a little old so I didn't see that example in mine. :)

Can12:03:55

Have a good day! 🙂

😉 2
🙂 2
Can07:03:41

I didn't see any usage of them in demo projects, if you leave very basic usage example would be awesome. 🙂

adamfrey13:03:11

I'm trying to isolate and understand a live-reload problem I'm experiencing when I try to add the shadow-css library to the starter-app repo. The problematic outcome that sometimes happens (it's hard for me to make it happen predictably) is that on a source code change the elements in the DOM remain, but get a display: none style attached to them, forcing me to reload manually in my browser. Can I get some help understanding what might be going wrong here based on electric's DOM implementation? I see https://github.com/hyperfiddle/electric/blob/master/src/hyperfiddle/electric_dom2.cljc#L47 which sets display: none on unmount, but it appears as though no other DOM elements are being added to replace the unmounted ones.

Geoffrey Gaillard14:03:00

Are you getting any error printed to your REPL or javascript console?

adamfrey14:03:04

no, nothing in either place. I can push up a fork of the repo if you are interested

Geoffrey Gaillard14:03:20

Thank you, I’ll give it a look

Geoffrey Gaillard16:03:01

I’m short on time to look into it today, sorry. I’ll get back to you

adamfrey16:03:27

no problem. Thanks, again

Geoffrey Gaillard10:03:27

We can reproduce the issue and also saw it elsewhere. Probably not related to shadow-css. This is on us, we’ll keep you posted.

👍 2
xificurC16:03:19

Hi @U06060CK0, we landed a fix where I've seen similar behavior and now it's gone. If you pull latest master and still find this behavior can you let us know?

adamfrey17:03:01

it appears that on d636c0f I am still able to reproduce the behavior I was seeing. I actually pared down the reproduction steps to trigger the behavior in the README on my fork of the starter app. https://github.com/AdamFrey/electric-starter-app

xificurC10:03:43

@U06060CK0 we pushed a fix for this, I also tested your repro steps with latest master commit and can no longer reproduce

adamfrey12:03:10

awesome. I pulled the latest commit and am also confirming that it's fixed on my end. Thank you!

👍 2
nivekuil22:03:48

with the electric root component node as a div (react ref)

(e/defn Main [dom-root]
  (binding [e.d/node dom-root]
    (e.d/pre (e.d/text "hi"))))
nothing happens, except for this stacktrace in the browser console

👀 2
2
nivekuil22:03:08

It looks like runtime/with is scheduled in a callback, and when it's fired the second arity <x is undefined

Dustin Getz22:03:55

I get a similar error from (e/client (new nil))

nivekuil22:03:56

yeah, but the (.-current ref) shouldn't be nil as it's in a if.. statement (see gist from last thread)

Dustin Getz22:03:41

the string ".-current ref" is not in the gist

Dustin Getz22:03:34

Passing electric-component through a clojure function is suspicious

nivekuil22:03:37

(defn start-electric [dom-root-ref electric-component]
  (hooks/use-effect (fn []
                      (if-let [x (.-current dom-root-ref)]
                        (let [electric-main (e/boot (electric-component. x))
                              reactor       (electric-main
                                             #(js/console.log "Reactor success:" %)
                                             (fn [error]
                                               (case (:hyperfiddle.electric/type (ex-data error))
                                                 :hyperfiddle.electric-client/stale-client (do (js/console.log "Server and client version mismatch. Refreshing page.")
                                                                                               (.reload (.-location js/window)))
                                                 (js/console.error "Reactor failure:" error))))]
                          #(reactor))
                        js/undefined))
                    [dom-root]))
is the same

nivekuil22:03:49

what should be I be doing instead of passing that?

Dustin Getz22:03:14

can you hardcode it and see if it works

Dustin Getz22:03:40

can i see the intended usage of (start-electric ...)

nivekuil22:03:03

but what exactly is happening when I pass electric-component?

Dustin Getz22:03:52

(e/def x ...) from clojure-land's perspective, macroexpands to (def x) and then adds the quoted electric expr as metadata

Dustin Getz22:03:08

so electric-component is nil, clojure resolved it as a clojure var to nil

nivekuil22:03:21

why is (meta Main) nil?

Dustin Getz22:03:00

(meta #'Main)

Dustin Getz22:03:29

also see defmacro def in electric.cljc

Dustin Getz22:03:16

To solve this, if you need to parameterize the electric entrypoint, i think you can use defmacro

nivekuil22:03:17

you attach it to the var, I see. forgot that was a thing you could do

Dustin Getz22:03:46

page here is a qualified symbol to an electric def, which is resolved in Pages earlier in the file

Dustin Getz22:03:12

the code is contorted because Electric does not have eval yet, and basically the electric compiler today drops any electric code that isn't reachable from the entrypoint

Dustin Getz22:03:44

so if you wanna be dynamic, you can use a symbol but it needs to be a static reference, if that makes sense, vocabulary is escaping me right now

Dustin Getz22:03:24

i gtg - sorry about the pain

Dustin Getz22:03:05

I will log a ticket to improve that error about >x is nil, that was really bad

nivekuil22:03:27

no worries, this is definitely challenging some assumptions I have about clojure

🙂 2
Dustin Getz23:03:39

haha in what way

nivekuil23:03:51

I never write macros, I think I use metadata for one system but that was IMO a mistake. I think just using qualified kws for everything in as global a scope as possible is the way to go

👍 2
nivekuil23:03:36

so I rarely have to think outside the "everything I care about is in the map of kw->whatever" mindset

nivekuil23:03:53

blame pathom, makes programming ez mode

Dustin Getz00:03:23

yeah i agree with you that clojure's metadata is not broadly useful, it's almost useful in so many situations

Dustin Getz00:03:20

hopefully we can reduce the macro pain as Electric matures. The particular issue you hit today probably can be solved in a future design

nivekuil23:03:48

if I render a component inside e/server

(e/defn Main [dom-root]
  (binding [e.d/node dom-root]
    (e/server
     (e.d/pre (e.d/text "hi")))))
shadow-cljs is not happy

2
nivekuil23:03:23

or

(e/defn Test []
  (e.d/text "hi"))

(e/defn Main [dom-root]
  (binding [e.d/node dom-root]
    (e/server (new (Test.)))))
to more closely match https://github.com/hyperfiddle/electric/blob/1bdd53bce5b5a2ebf69ac25bc5ae9eb564be692f/src-dev/user_main.cljc#L95

nivekuil23:03:44

oh, I guess it has to be like this

(e/defn Test []
  (e/client (e.d/text "hi")))

(e/defn Main [dom-root]
  (binding [e.d/node dom-root]
    (e/server (new (Test.)))))

Dustin Getz02:03:10

the error “cannot resolve dom/node” means accessed from the wrong side

Dustin Getz02:03:47

if the e/client or e/server is omitted, it is inherited from the caller

Michael W23:03:35

How to make an svg clickable? I have tried quite a few ways but can't get it to work right. If I wrap it with a ui/button it works but puts the button graphic under the svg, which I don't want. Is that a style thing?

Michael W23:03:41

Figured this out with styles:

(ui/button (e/fn [] (do-something))
  (dom/style {:background "transparent"
              :border 0})
  (svg/svg ...))

Dustin Getz02:03:16

i don’t know the answer to this, i would start with stackoverflow probably to find out how it ought to work and then we can figure out how to do it in electric

Geoffrey Gaillard09:03:57

(svg/svg
  (dom/on "click" (e/fn [event] (prn "svg clicked")))
  (svg/rect
    (dom/on "click" (e/fn [event] (prn "rect clicked")))))

👀 2
nivekuil23:03:13

ok, I was under the impression that a e/defn is like a react component and the whole thing would render if something it closes over changes, but it really is kind of mind blowing how granular the effects are

nivekuil23:03:58

at the same time, I can't figure out (nor do I have an actual use case) how effects should be coupled, like logging something when the text of a div changes

👀 2
Dustin Getz03:03:04

((fn [] (prn 1) (prn 2))) will fuse the effects, because clojure functions aren’t reactive inside. we could provide a macro for that ‘e/fuse’ but like you we have not found a real use case, each time we reached for it so far it turned out to not be the best option