Fork me on GitHub
#clojurescript
<
2019-10-25
>
andy.fingerhut06:10:10

With some changes I made to the core.rrb-vector library recently, the ClojureScript compiler gives a warning that looks reasonable to me, but yet the code seems to work anyway. I was curious if I should be worried about this warning, because code that causes the warning to appear could break with the next ClojureScript compiler release, or whether somehow the fact that it seems to work is really normal somehow (and if so, how?). I've boiled it down to a tiny sample Leininge project here: https://github.com/jafingerhut/ouroboros

andy.fingerhut06:10:30

The README contains sample output from compiling and running the tests of the code, with the warning message, and a brief explanation of the structure of the code, which is only a couple of dozen lines long.

kwladyka09:10:38

Hi guys, I had a discussion with 1 developer about state for forms during filling it. I am using r/atom to keep state for forms in Re-frame. I also saw everybody doing it like this. But today I meet somebody who use re-frame DB instead of reagent.core/atom. What is your way? How are you doing it? And WHY?

kwladyka10:10:36

What is better practice in your opinion?

kwladyka10:10:48

How common is using re-frame DB instead of reagent.core/atom ?

kwladyka10:10:34

I am asking, because I did library for form validation and I didn’t consider using re-frame DB.

thheller10:10:49

I don't really have an answer because I don't use either re-frame or reagent but in general using the DB decouples it from the component itself

kwladyka10:10:54

So I want to undestand things to make choices and potentially improve library

thheller10:10:06

so if it gets unmounted for some reason the form state isn't lost

kwladyka10:10:05

exactly, I think when filling the form and user click on other link you don’t want to keep this state

thheller10:10:21

maybe you do maybe you don't. depends on the use case

kwladyka10:10:56

so you prefer to use 1 DB? Even for filling form?

thheller10:10:18

depends. sometimes yes, sometimes no

kwladyka10:10:30

> I don’t use either re-frame or reagent om.next?

kwladyka10:10:09

so do you prefer it when you want to keep the state of not finished (submited) form?

thheller10:10:13

complex forms I generally keep in the DB, simple forms with one or two inputs that I'm fine to lose I'm often fine with local state

kwladyka10:10:19

Can you give me an example of use case?

thheller10:10:24

not really, it is all way too specific to the app itself

kwladyka10:10:13

hmm, how do you deal with abandoned forms then? Keeping in DB? When user come to form see the state from last time?

kwladyka10:10:27

or clear the state in DB each time when user start to fill form again?

kwladyka10:10:12

I can imagine forms without submit button. Like for example github settings. You click something or lost focus and field is submited.

kwladyka10:10:24

it can be a use case

p-himik10:10:47

It all depends on the use-case. It's similar to the way you can work with React input components. Sometimes you want a controlled component, sometimes you don't.

thheller10:10:29

you'll generally have some kind of event that you can hook into

thheller10:10:11

so you could hook into the componentWillUnmount lifecycle and trigger the removal of the form data there

thheller10:10:37

or just any other re-frame event that the user can trigger will remove the data

thheller10:10:57

the answers will always be very specific to whatever you are trying to do

kwladyka10:10:20

hmm it sounds like a unnecessary complexity vs just use atom in form component. But maybe I don’t see good use case.

p-himik10:10:43

Unrelated question - do I understand it correct that I cannot parametrize the field that I want to set with set!? I.e. I want onerror to be a parameter in a form like (set! (.-onerror n)).

kwladyka10:10:40

Thank you for the input. I have rethink my life 🙂

p-himik10:10:21

@kwladyka There's also re-com library. It's not concerned with forms, it's more low level. But it explicitly makes a choice of not allowing uncontolled components. You always have to provide :on-change and :model or something like that. This approach sometimes leads to a few boilerplate lines, but I don't think it can lead to a developer not being able to achieve something with such a library.

p-himik10:10:03

E.g. you can use re-com with both re-frame with its subscriptions and events and Reagent with its local/global ratoms.

thheller10:10:25

@p-himik correct, the fields for set! have to be static

kwladyka10:10:43

Does it work only for re-frame / reagent, but not om.next / fulcro ?

p-himik10:10:35

@thheller Thanks! @kwladyka Yes, it uses reagent internally, and re-frame is also built on top of reagent.

p-himik10:10:52

But I don't think that it actually has to use reagent. It could be abstracted away without too much hassle. Well, assuming the target is React.

kwladyka10:10:05

I want to keep library independent. I have to rethink solution once again. It is design to use atom or reagent.core/atom or different kind of atom, but not to use something what is not atom and is not only for state of this form. Probably I have to provide settings to set how to update state.

kwladyka11:10:48

So once again thank you for discussion. I have to figure out how to adapt it to use with DB also.

p-himik11:10:17

You can make it possible for a user to choose between controlled and uncontrolled forms. I can't see how it can be limiting for users, but it definitely puts some burden on you as the library's author and maintainer. DB in re-frame is nothing special. Components never work with it directly - they just accept atoms or values (received from re-frame subscriptions) and call some callbacks (that generally should dispatch a re-frame event).

kwladyka11:10:41

What do you mean by controlled and uncontrolled ?

kwladyka11:10:51

yes, but my initial idea was to keep form in separated state unless submit. Now this idea changed to let user keep it separate or add to 1 global state of the app.

p-himik11:10:19

tl;dr: uncontrolled components can manage their own internal state. They can be asked their current value and they can emit an event when a value is changed by something. Controlled components don't manage any internal state that's not crucial for their work (e.g. you don't want to expose a progress indicator of a component that talks to some backend - it has its state, but it's an implementation detail), so they must receive a value and can receive a change handler.

borkdude11:10:15

I have this in deps.edn:

:prod {:extra-paths ["src-cljs-prod"]
                  :main-opts ["-m" "cljs.main" "-co" "cljs.edn prod.cljs.edn"
                              "-O" "advanced"
                              "-d" "out" "-c" ""]}
When I compile I get this:
$ clj -A:prod
Compile sources, elapsed time: 244.941075 msecs
Compile sources, elapsed time: 21.391 msecs
Execution error (BindException) at java.net.PlainSocketImpl/socketBind (PlainSocketImpl.java:-2).
Why does it try to bind to a port?

borkdude11:10:09

replacing -co with "cljs.edn:prod.cljs.edn" does what I want, but the behavior is a bit strange

thheller11:10:37

is there more to this error? seems weird that it is trying to bind a socket?

borkdude11:10:59

it might try to start a REPL or something? this is the only thing I'm seeing as the output

thheller11:10:34

this is getting interpreted by bash I guess so it'll end up calling cljs.main -co cljs.edn prod.cljs.edn

thheller11:10:56

dunno what that argument is interpreted as then as it is no longer -co

thheller11:10:14

at least I think that is how it works

borkdude11:10:26

the path delimiter as a colon, that's the correct way?

borkdude11:10:32

(on Mac and Linux)

thheller11:10:44

no clue, I don't use cljs.main or deps.edn for that matter

thheller11:10:07

I have seen others using , to replace all spaces

thheller11:10:28

but not sure that'd work in this case

borkdude11:10:42

yeah, then I got file not found 🙂

thheller11:10:47

["-m" "cljs.main" "-co" "cljs.edn" "-co" "prod.cljs.edn" might do it

erik11:10:11

is the Code Splitting feature appropriate for the purposes of writing a multi .html+.js browser extension?

thheller11:10:30

depends. some scripts run in different contexts so they need different setups.

👍 4
erik11:10:41

do you happen to have any pointers? especially anything specific to writing browser-extensions?

thheller11:10:02

shadow-cljs has some support for writing chrome extensions but it isn't documented anywhere besides the issue itself https://github.com/thheller/shadow-cljs/issues/279

thheller11:10:25

it'll make use of code splitting where appropriate automatically

erik11:10:17

I think I want to stick with figwheel-main for now... but so all-in-all, code splitting is appropriate, as long as I handle the context specifics which you mention?

thheller11:10:16

I honestly can't remember most of the details. Haven't done anything browser extension related in over a year

thheller11:10:30

but yes it sometimes make sense to split

erik11:10:47

ok, I'll give it a try

borkdude11:10:20

@thheller btw, I appreciate the quick responses and helpfulness from your side!

❤️ 12
kwladyka11:10:06

Yes, he can’t be human :) He knows all answers.

4
isaac12:10:47

cljs start a server not serve on some staitic files, such as *.cur, *.woff

Filipe Silva14:10:19

heya, what's the recommended way of applying js tagged template literals? Is it to instead call the function directly?

p-himik16:10:14

I've never actually worked with the template literals, but tagged template literals seem... strange, to say the least. I would definitely just call a function.

Filipe Silva16:10:15

they enable some interesting things

Filipe Silva16:10:37

some js libraries, like https://emotion.sh/docs/introduction, leverage them

Filipe Silva16:10:05

so in that sense the interop is relevant, because if you want to use the library you have to be able to use tagged template literals

p-himik16:10:47

Hmm, I see, thanks. Maybe, to support a similar calling convention, it makes sense to create a macro for that.

itaied16:10:56

using re-frame, I have registered an fx using re-frame/reg-fx where I make an http call. How can I set the response to the db ?

dpsutton16:10:07

https://github.com/day8/re-frame-http-fx/blob/master/src/day8/re_frame/http_fx.cljs#L42 check out how the reframe http-fx lib works. the success/failure handlers are reframe events passed in that are dispatched with the resultant responses

itaied16:10:27

actually im not using http directly, but some other effect. should i dispatch an event when it finished to update the db?

itaied16:10:16

got it. thanks

isaac17:10:56

How to export prototype properties, eg

(ns a.b)

(defn ^:export mkfoo []
   (reify Object
     (foo [this])))

;; call in js
;; f = a.b.mkfoo(); 
;; f.foo() not working

hiredman17:10:27

(defn ^:export foo [thing] (.foo thing))

hiredman17:10:07

f = a.b.mkfoo(); 
a.b.foo(f);

hiredman17:10:01

I mean, I dunno, I don't really write any clojurescript, but I think that is the correct thing to do given what I understand about :export and the google closure compiler

hiredman17:10:37

and assuming that reify is valid, as I said I don't write clojurescript, and that wouldn't be valid in clojure

andy.fingerhut19:10:19

When one runs a Node-based ClojureScript REPL using a command like this: clojure -Sdeps '{:deps {org.clojure/clojurescript {:mvn/version "1.10.520"}}}' -m cljs.main --repl-env node, what cljs compiler options are used? If there are warning messages from cljs compilation, are they sent to the bit bucket somehow?

andy.fingerhut19:10:59

I have a project where if I use lein cljsbuld ... to run tests, I see compilation warnings, but when I run tests using a command like the above, plus -e (clojure.test/run-tests 'my.test.namespace) at the end, there are no warnings. I was hoping to be able to see them using the clojure command method, too.

dpsutton19:10:02

(defrecord NodeEnv [host port path socket proc state]
  repl/IReplEnvOptions
  (-repl-options [this]
    {:output-dir ".cljs_node_repl"
     :target :nodejs})
in cljs.repl.node

dpsutton19:10:10

not sure if that fully answers it or not though

andy.fingerhut19:10:04

It might. I have in some cases seen a .cljs_node_repl directory created, but not always, and I don't know yet what the difference is in the situations where it does create it, vs. not.

andy.fingerhut19:10:29

I can run a node-based cljs repl given my command above, and evaluate expressions in it, and no such directory is created. Weird.

mazin20:10:33

has anyone been able to get weasel (https://github.com/nrepl/weasel) working with the latest cljs?