Fork me on GitHub
#clojurescript
<
2018-10-30
>
dnolen01:10:01

@aron probably just a bug, the REPL we ship still needs a lot of work - but it doesn't get a ton of love since it mostly used for testing + Quick Start - other REPLs like Figwheel will probably have whatever config you need to do what you want

dnolen01:10:23

well I know it does since I've done exactly what you're talking about before šŸ™‚

aron03:10:51

@dnolen heh, thanks šŸ™‚

exit213:10:14

Hi all, Iā€™m trying to resolve this warning Iā€™m getting on build:

Oct 30, 2018 1:42:17 PM com.google.javascript.jscomp.LoggerErrorManager println
WARNING: resources/public/generated/js/inferred_externs.js:109: WARNING - name goog is not defined in the externs.
goog.string.StringBuffer;
^^^^

lilactown14:10:39

:thinking_face: is it possible to get ns-publics of a namespace at macro-time?

dnolen15:10:48

see cljs.analyzer.api

šŸŽ‰ 4
lilactown15:10:28

do people prefer hiccup to s-expressions for representing html?

šŸ‘ 4
justinlee16:10:11

youā€™d have to quote everything if you used sexps, no? I always assumed thatā€™s why vectors were preferred. (maybe thatā€™s not what youā€™re talking about?)

lilactown16:10:58

you could use factory functions instead of data

lilactown16:10:44

(defn factory [el]
  (fn [& args] (apply react/createElement el args)))

(def div (factory "div"))

(def MyComponent
  (factory (fn [props]
             (div "Hello!"))))

lilactown16:10:29

macros make the MyComponent definition palateable

justinlee16:10:46

I guess Iā€™d rather pass a vector and let factory sort it out rather than introduce a macro whose only purpose is to avoid quoting

lilactown16:10:28

:thinking_face: not sure those are the two options

lilactown16:10:11

I'm looking at removing the need of controlling the render tree in CLJS-land. so we should be just using regular ol' react components (functions or classes) that return react elements

lilactown16:10:21

in order to use hiccup, we have to use a macro to convert [:div "blah"] to (react/createElement "div" nil "blah")

lilactown16:10:37

we can avoid macros by using factory functions instead

lilactown16:10:30

defining components already needs some macro-ness to remove the boilerplate for converting props into clojure maps

lilactown16:10:48

so it's easy to also add, "create the factory for this component" to the macro anyway

dnolen17:10:56

I would avoid complications

dnolen17:10:58

I would argue - stick with Hiccup syntax and do this without macros

dnolen17:10:30

on a current project the benefit is itā€™s way easier to interact/debug hiccup then React stuff

dnolen17:10:52

for React just supply some tree walking fn that becomes a no-op in Clojure

dnolen17:10:31

then you can share templates, and rendering hiccup serverside is a middleware-ish thing

dnolen17:10:56

thatā€™s how a current client project Iā€™m working on is set up and itā€™s simple and gets the job done

dnolen17:10:16

in Om I opted for fn calls - due to thinking about perf - but from what Iā€™ve seen over the past almost 5 years

dnolen17:10:31

thereā€™s smaller population that needs the perf

dnolen17:10:56

and just implementing precise reconciliation will blow away any other perf stuff you could think about

justinlee17:10:14

that seems like a nice, simple setup

justinlee17:10:35

the only thing i would like to know is what does interop look like

dnolen17:10:57

to me Hiccup is a local maxima - youā€™re unlikely to come up with something better thatā€™s as easy to work with

lilactown17:10:28

the #1 thing for me is that any "component" is just a React component. not a special CLJS-only thing

dnolen17:10:44

right thatā€™s how Om works

dnolen17:10:51

but I donā€™t really think itā€™s that important

lilactown17:10:07

I suppose if perf is not important you could parse the hiccup in the render function?

dnolen17:10:11

anyways Iā€™m just telling my opinion after doing this stuff for a while now šŸ™‚

lilactown17:10:26

I do appreciate it. It is making me question myself

dnolen17:10:54

the React hook thing rules

dnolen17:10:57

I looked at your repo

dnolen17:10:03

I think everything youā€™ve done is fine

dnolen17:10:07

donā€™t do compile time stuff

dnolen17:10:13

no macros, just walk run time

dnolen17:10:17

and no-op in Clojure

lilactown17:10:00

OK, I'll explore that and run some experiments šŸ˜„

justinlee17:10:33

thought: offer a macro if the hiccup is really static and then just opt in if you need it (?). i just happen to work in an environment where this kind of overhead is never the performance bottleneck

lilactown17:10:31

my experiments are all in https://github.com/Lokeh/hx right now. currently, it's very macro heavy

dnolen17:10:54

yeah if you drop macros, I think everything will become simple and easy to implement

lilactown17:10:39

hx.react/c is the hiccup compiler macro. I could move that to runtime and it would probably simplify things

dnolen17:10:46

I also suspect with transducers the performance hit wonā€™t be that meaningful client-side

dnolen17:10:55

remember that vectors < 32 items are inlined into the source

dnolen17:10:04

and transducers will just loop over that single internal array

šŸ¤Æ 8
lilactown17:10:34

I did not know that. that's pretty damn cool!

lilactown17:10:12

I think that having a macro for defining components will still be needed. marshaling props into CLJS data structures is not fun

dnolen17:10:59

why do you need to marshal props with React Hooks?

dnolen17:10:02

unless I missed something

lilactown17:10:18

it's not specific to react hooks, but react components in general.

(defn my-component [props] ;; <-- props is a JS object
  (let [name (goog.object/get props "name")]
    [:div "Hello, " name "!"]))

lilactown17:10:14

I would prefer to shallowly convert it to a CLJS map so that it could be destructured, etc.

lilactown17:10:31

same thing for passing in props to components. you can't pass in just a map to a React component as props because it introspects & manipulates the props and expects it to be a normal JS object

thheller17:10:01

yeah thats my concern about hooks as well. the inputsAreEqual function that checks the extra inputs argument doesn't support CLJS equality semantics which may be annoying to work around

thheller17:10:40

hope they expose something more low level so we can create our own hooks

dnolen17:10:19

@lilactown hrm when do they introspect props? So hooks does or doesnā€™t support plain old fns?

lilactown17:10:48

Iā€™m talking about plain react-component-as-a-function. no hooks yet

lilactown17:10:13

e.g. they add a children prop

dnolen17:10:25

but if the react component is a fn when do they have a chance to touch props?

dnolen17:10:40

(sorry I really donā€™t know, I didnā€™t see anything like this when I looked at what they wrote up)

dnolen17:10:48

I havenā€™t tried it myself - so missing details here

lilactown17:10:20

(defn example [props]
  (react/createElement "div" nil (prn-str props)))

;; rendering:
(react/createElement example {:name "Suzy"} "asdf")
output on screen:
#js {:meta nil, :cnt 1, :arr #js [:name "Suzy"], :__hash nil, "cljs$lang$protocol_mask$partition0$" 16647951, "cljs$lang$protocol_mask$partition1$" 139268, :children "asdf"}

lilactown17:10:01

it gets weird

thheller17:10:22

react/createElement copies the object but you can just create the element object directly instead which skips that copy

lilactown17:10:07

:thinking_face: color me curious. what do you mean?

thheller17:10:23

just need to construct this object basically

thheller17:10:57

although I'm no longer sure about the owner thing. it used to be deprecated, might not be anymore

lilactown18:10:27

hmm, Iā€™m worried about using anything thatā€™s not a public API

thheller17:10:00

there was a babel plugin that did that. forgot the name though

dnolen17:10:20

@lilactown but does React actually need that children?

dnolen17:10:29

you props doesnā€™t use it

dnolen17:10:38

so even though it mutates the top level wrapper of the persistent data structure

dnolen17:10:46

doesnā€™t matter since nobody is ever going to look at field

lilactown17:10:18

if example did need to access children, though?

dnolen17:10:23

ā€œif a tree falls in a forest ā€¦ā€

dnolen17:10:29

why would it need to?

dnolen17:10:33

you wrote it!

lilactown17:10:06

I think there are many times when people want to use the children prop šŸ˜… unless Iā€™m missing your point

dnolen17:10:15

in ClojureScript???

dnolen17:10:28

I canā€™t think of any times where I needed that

dnolen17:10:43

the only time I dealt with children was when I was writing Om

dnolen17:10:46

and it was annoying

lilactown17:10:40

are you saying that you donā€™t see the point of being able to render an element passed in as a prop? or that you just donā€™t use Reactā€™s children prop to do that?

lilactown17:10:02

the former I canā€™t agree with. we do that a ton at work to share styling and logic

dnolen17:10:08

I just donā€™t understand what youā€™re trying to achieve?

dnolen17:10:17

[:div props children...]

dnolen17:10:20

thatā€™s hiccup

dnolen17:10:24

since you want to walk this structure anyway

dnolen17:10:33

I donā€™t see why you cannot set up the transformations when you need them - if theyā€™re required

lilactown17:10:41

I want to do this:

(defn example-2 [{:keys [name children]}]
  (into 
    [:div 
      [:div "Hello, " name "!"]]
    children)

(defn app [_]
  [example-2 {:name "Uma"} [:div "I'm a child"]])

lilactown18:10:44

thatā€™s the API I want

dnolen18:10:49

well IMO that doesnā€™t really seem reasonable, since thatā€™s not hiccup

dnolen18:10:56

hiccup doesnā€™t have implicit splicing like that

lilactown18:10:41

you mean children passed in directly into the vector?

dnolen18:10:03

but also you could do that with syntax-quote

dnolen18:10:14

I would argue for thinking harder about whether you really want children

dnolen18:10:35

itā€™s worth looking around at how people actually use Reagent or even Om Next, we donā€™t pass around children

dnolen18:10:39

feels like a JS-ism to me

dnolen18:10:51

into would work like youā€™ve changed it up there

lilactown18:10:16

I donā€™t want to get caught up with into/quote-splicing/etc.

dnolen18:10:17

but again, Iā€™m skeptical

lilactown18:10:06

the point is that I want to be able to read props and pass in props to any React component just like in JS

dnolen18:10:24

this just seems more idiomatic and in line with what Hiccup intends

dnolen18:10:04

Iā€™m just saying I donā€™t know why you need to carry over the children pattern thing

lilactown18:10:13

my point is that it still requires some special marshaling of the props received by the function before we can destructure it like that

lilactown18:10:39

(defmacro defnc [name props-bindings & body]
  `(defn ~name [props#]
     (let [~@props-bindings (hx.react/props->clj props#)]
       ~@body)))

dnolen18:10:42

I still donā€™t follow that part either?

dnolen18:10:55

why do you want to convert JS to CLJ?

lilactown18:10:49

I guess, ultimately, Iā€™m trying to maximize the ability to interop with the React ecosystem. I expect that the props# will be a normal JS obj. so I could e.g. pass this in to a HOC I installed from npm

lilactown18:10:46

likewise when I write [MyComponent {:foo "bar"}], MyComponent could be a React component written by me in CLJS or one I installed from npm and I donā€™t have to care

dnolen18:10:17

right but this seems backwards to me

dnolen18:10:40

you wrote it in CLJS first which is never ā€œjust going to workā€ with JS

dnolen18:10:59

so it seems to me you should write this stuff CLJ first

dnolen18:10:02

JS users 2nd

dnolen18:10:37

(unless of course you want to limit the audience to CLJS bootstrapped or something like that)

lilactown18:10:52

Iā€™m thinking of it from the perspective of a CLJS user trying to consume JS components. adopting JS semantics I think greatly helps with the frustration I have had with reagent

lilactown18:10:02

and I donā€™t think itā€™s that costly. maybe Iā€™m wrong

lilactown18:10:20

the React ecosystem has components, frameworks, new features, devtooling, etc. that I could be leveraging but thereā€™s friction due to too many things that are ā€œCLJ-firstā€

lilactown18:10:35

Iā€™m trying to find a balance that allows me to be the most productive

dnolen18:10:51

Iā€™d say Iā€™m on the fence about the JS components

dnolen18:10:08

shimming them is generally a reasonable amount of effort

dnolen18:10:24

and a lot of times you need to think twice anyway - theyā€™re huge dependencies

dnolen18:10:42

probably the only suggestion I would say would be to think about separating the couple of useful parts you will need to build

dnolen18:10:10

i.e. the fast runtime walker that converts hiccup -> React components - which is generally useful

dnolen18:10:10

and the sugary stuff

šŸ‘ 4
lilactown18:10:04

in the implementation you were talking about before, do you walk the whole tree? or just the body of a component?

dnolen18:10:51

I would just walk the body of a component

dnolen18:10:03

since that opens the door for someone who wants to do a reconciler with precise updates

dnolen18:10:50

React hooks definitely opens the door to doing a lot of stuff in a more lightweight way for ClojureScript

šŸ’Æ 8
jaawerth19:10:46

@lilactown out of curiosity, what react tooling and libraries do you find you can't do without, and which are frustrating to integrate with reagent? I ask because I've yet to start my first non-toy reagent project to get a feel for the real-world work experience with it, so I'm curious about the pitfalls, as so far I like the feel of it better than react itself

lilactown19:10:17

Anything involving HOC or render-functions

ā˜ļø 8
lilactown19:10:31

E.g. we wanted to use apollo

lilactown20:10:05

And react spring

borkdude22:10:52

clojure.spec.test.alpha/check gives me back a seq of map with keys: (:spec :clojure.spec.test.check/ret :sym) is this planned for clojurescript as well? Iā€™d like to see if my num-tests argument propagated correctly (which does not seems to work in planck).

mfikes22:10:45

@borkdude We recently ported all of the Clojure spec changes to ClojureScript, so it may be worth checking to see if master has that new behavior

pablore23:10:19

For reacters here, would you consider the Redux store a kind of an atom? Or agent? Or something else?

lilactown23:10:53

itā€™s very similar to an atom. the difference is that your app automatically re-renders when itā€™s changed, and you (usually) dispatch a named action instead of a direct state manipulation

lilactown23:10:35

itā€™s quite easy to build the reducer pattern that redux popularized on top of an atom

lilactown23:10:44

re-frame is pretty much our ā€œreduxā€ for reagent codebases and it works off of a single atom, and you dispatch actions and subscribe to it much like redux