Fork me on GitHub
#reagent
<
2018-09-13
>
sveri13:09:04

Here I am again with a react interop question. Following code: <MuiPickersUtilsProvider utils={DateFnsUtils}> from https://github.com/dmtrKovalenko/material-ui-pickers needs to be translated to cljs code, but I cannot get it work again. I tried: [:> MuiPickersUtilsProvider {:utils DateFnsUtils} which does not load the page and: [:> MuiPickersUtilsProvider {:utils (reagent/reactify-component DateFnsUtils)} which loads the page, but when I try to show the date picker it throws this error: TypeError: utils.date is not a function

sveri13:09:12

Any idea how to make that one work?

sveri13:09:21

DateFnsUtils is declared like this: declare class DateFnsUtils extends Utils<Date> { } if that is of any help.

sveri13:09:31

and from a plain javascript perspective is a function.

valtteri17:09:48

@sveri you could try {:utils (reagent/as-element DateFnsUtils)}

valtteri17:09:44

No clue if it works or not. šŸ™‚

justinlee17:09:25

I donā€™t understand this: declare class DateFnsUtils extends Utils<Date> { }. whatā€™s that declare doing there?

justinlee17:09:32

thatā€™s neither cljs nor js

justinlee17:09:56

also, if thatā€™s supposed to be js, then DateFnsUtils is neither a reagent component nor a react component

justinlee17:09:30

so you shouldnā€™t need reactify-component nor as-element

valtteri17:09:57

In that case you could try with #js

justinlee17:09:08

no you donā€™t need that. reagent already does clj->js on the prop map for you when you use :>

justinlee17:09:15

thereā€™s something else wrong

justinlee17:09:44

its hard to me to diagnose because iā€™m not familiar with the underlying library

justinlee17:09:10

oh that declare thing is a typescript annotation

justinlee17:09:00

okay @sveri my guess is that you are just not getting DateFnsUtils imported properly in the page. are you using shadow-cljs? try printing it out to see what it is

sveri18:09:43

@valtteri @lee.justin.m Thanks for your suggestions. It was imported properly and yes the declaration was in typescript, I should have added that. Anyway {:utils (reagent/as-element DateFnsUtils)} indeed works, thank you šŸ™‚

justinlee18:09:10

weird that doesnā€™t make any sense but Iā€™m glad it worked

dimovich20:09:27

I'm trying to use the same components code (cljc) from both Reagent and Hiccup, but it seems you have to use some kind of wrapper because Hiccup doesn't accept [my-component-fn ...], it needs (my-component-fn ...)

dimovich20:09:44

maybe I'm missing sth, and there is a simpler way, but here is my current approach

dimovich20:09:55

would appreciate any suggestion

justinlee20:09:07

@dimovich i donā€™t really understand the question

justinlee20:09:12

what are you trying to accomplish?

dimovich20:09:15

(defn child-component []
  [:div "hello"])

(defn parent-component []
  [:div
   [child-component]])

dimovich20:09:58

@lee.justin.m I want to use parent-compoent in Reagent -> [parent-component] and also from Hiccup (parent-component)

dimovich20:09:12

but Hiccup doesn't understand [child-component] form

justinlee20:09:32

oh sorry. so people tend to use hiccup as a generic description (i.e., ā€œreagent uses hiccupā€)

justinlee20:09:05

i mean, if you have two libraries that accept different data formats, I think you are going to have to do some data conversion

dimovich20:09:21

when I say Hiccup, I mean server-side rendering

dimovich20:09:56

you don't have Reagent on server-side, so when generating the page, it's nice to use the same code as on the client

dimovich20:09:36

yeah, but it uses a JS engine

dimovich20:09:40

why not use just Clojure?

justinlee20:09:53

because youā€™re going to need something that understands react

dimovich20:09:02

you don't have to

dimovich20:09:16

you generate the same markup, and then react will pick up the markup

justinlee20:09:40

JSX markup isnā€™t really markup. it is a DSL that gets translated into a bunch of normal javascript

justinlee20:09:47

at compile time

justinlee20:09:13

so you canā€™t render to some kind of jsx lookalike on the server and then handle that on the client. you need to actually compile to javascript

dimovich20:09:28

you don't have to

dimovich20:09:55

the code I posted before, it will generate HTML in the end, be it reagent or hiccup

dimovich20:09:35

react will take this html (generated server-side) and will overwrite it with it's own HTML

dimovich20:09:47

but it will be identical, so no redraws

dimovich20:09:48

that's how we do it for our current project... it works pretty well, but you need to wrap those common components

justinlee20:09:20

somehow the server side needs to understand react. this is only even conceptually possible in your example because it has a 1-to-1 relationship with plain html. what happen when you have a big react object with state and refs and so forth?

dimovich20:09:32

here comes re-frame to the rescue... it's also written in cljc, so you can use same subscriptions both client-side and server-side

justinlee20:09:07

let me back up: how can you expect to do SSR without using 'react-dom/server'?

justinlee20:09:20

donā€™t you need ā€˜renderToStringā€™

dimovich20:09:38

on server-side you use hiccup/html

dimovich20:09:00

on client-side you use reagent/render

justinlee20:09:18

well for the very reason you are asking, i donā€™t see how thatā€™s going to work unless you emulate react semantics in clojure

dimovich20:09:46

react is just a client-side dom abstraction, you don't have to take it into consideration

justinlee20:09:55

something needs to understand what you mean when you write [my-component prop1 prop2], and that thing is usually the react-dom/server javascript package

dimovich20:09:18

that's the role of reagent

justinlee20:09:07

no but reagent just gets you from cljs to a bunch of react javascript calls. it doesnā€™t take you all the way to html

justinlee20:09:29

thatā€™s why you need renderToString

dimovich20:09:15

When using hiccup, [my-compoent prop1 prop2] needs to be (my-component prop1 prop2) (a function call)

dimovich20:09:32

that's what my question was all about, is there a way to avoid this?

dimovich20:09:07

because now I use a macro to change the form depending if its clojurescript or clojure

justinlee20:09:55

i donā€™t see how. but worse, i donā€™t see how that conversion will work with form-2 and form-3 components but maybe iā€™m missing something. itā€™ll only work when your render function just returns plain hiccup and is a pure function of its arguments

dimovich20:09:14

yeah, it has to be a pure function. You can have both form-1 and form-2 components both on client and server.

dimovich20:09:55

but that's enough for generating server-side the front page

justinlee20:09:58

isnā€™t the website static if the entire component tree can be rendered in that way?

justinlee20:09:50

well anyway it sounds like your solution is fine. i doubt thereā€™s any standard or easier way to doing what you are doing

justinlee20:09:58

itā€™s crazy that it works at all šŸ™‚

dimovich20:09:56

yep, it's a nice surprise... šŸ™‚

dimovich20:09:30

regarding static site... it is, if you're careful with your components code

dimovich20:09:53

there is also a nice collection of libraries http://thi.ng that provide visualizations, also written in cljc, so you can generate same charts both client side and server-side

justinlee21:09:28

holy moly that website hurts my eyes

justinlee21:09:57

wow there is a lot of stuff in that github repo