reagent

A minimalistic ClojureScript interface to React.js http://reagent-project.github.io/
lilactown 2021-01-12T03:44:13.019500Z

if the component has propTypes set on it, you can access it via ClojureScript like:

(.-propTypes Button)

lilactown 2021-01-12T03:44:49.019700Z

however, this is something that the author of the JS component elects to do. not everyone does it consistently

2021-01-12T05:27:39.020700Z

Hi, I am new to clojurescript and reagent, so this is a very noob question. How do I use spread operator to pass all props to a child component in reagent?

<Box {...props}>
Thanks.

seancorfield 2021-01-12T05:30:08.022700Z

@chin321 You posted a nearly identical question in #re-frame just a few minutes ago. We generally discourage cross-posting of question and ask folks to just be a bit patient about getting a question answered when folks are around. Right now it's after midnight on the East Coast of the US so there's fewer folks here than during either Europe's day or America's day.

seancorfield 2021-01-12T05:30:47.023700Z

I have to say, I don't really understand your question... Can you provide an example in ClojureScript to illustrate what you're asking about?

emccue 2021-01-12T05:30:47.023800Z

@chin321 [:> Box props]

1👍
emccue 2021-01-12T05:31:05.024500Z

the spread operator is only needed in JS for copying the object

seancorfield 2021-01-12T05:31:20.025200Z

So :> means "apply" basically?

emccue 2021-01-12T05:31:20.025300Z

if you have other options

emccue 2021-01-12T05:31:36.025700Z

[:> Box (merge {:open true} props)]

emccue 2021-01-12T05:31:40.025900Z

just merge the maps

emccue 2021-01-12T05:31:56.026300Z

@seancorfield no, its whats needed for interop with a react component

emccue 2021-01-12T05:32:16.027100Z

so if you have a react component, to wrap it into reagent one way to do it is to use [:>

seancorfield 2021-01-12T05:32:23.027500Z

Cool. I'm only just getting back into cljs after a seven year gap so this is useful for me.

2021-01-12T05:32:35.027800Z

I figured it is more suited to this channel, so I deleted the question from #re-frame. Thanks for letting me know.

emccue 2021-01-12T05:32:42.028100Z

I'm just getting back into it after ~4

emccue 2021-01-12T05:33:12.028700Z

but its just syntax sugar around adapt-react-class

emccue 2021-01-12T05:33:28.029Z

if you have a reagent component

emccue 2021-01-12T05:33:41.029300Z

so a function that returns hiccup

seancorfield 2021-01-12T05:33:53.029700Z

Thanks :thumbsup::skin-tone-2:

emccue 2021-01-12T05:33:59.030Z

its up to you to structure the signature of that function such that it will accept "passthrough" options

emccue 2021-01-12T05:35:02.031500Z

(defn box [open? color]
  ...)

Malik Kennedy 2021-01-12T05:35:10.031800Z

https://github.com/reagent-project/reagent/blob/master/doc/ReactFeatures.md There are some other weird looking reagent hiccup forms like :f> and :<>

emccue 2021-01-12T05:35:14.032Z

so in this case, you have to manually pull out what you want to pass

emccue 2021-01-12T05:35:28.032300Z

because it expects two "positional arguments"

emccue 2021-01-12T05:35:33.032500Z

[box true "red"]

emccue 2021-01-12T05:35:47.032900Z

[box (:open? props) (:color props)]

emccue 2021-01-12T05:36:02.033300Z

if you write it such that it accepts a map, you can just pass the map as is

emccue 2021-01-12T05:36:18.033700Z

(defn box [{:keys [open? color]}]
  ...)

emccue 2021-01-12T05:36:43.034400Z

[box {:open? (:open? props) :color (:color props)}]

emccue 2021-01-12T05:36:48.034600Z

[box props]

emccue 2021-01-12T05:37:04.035100Z

[box (merge {:color "red"} props)]

emccue 2021-01-12T05:37:25.035600Z

all react components take some "props object", so its more uniform there

seancorfield 2021-01-12T05:41:05.036600Z

Would you say it's "best practice" to write components to accept a single map argument? That seems to fit with more general Clojure(Script) recommendations when you otherwise would have arbitrary arguments...

emil0r 2021-01-12T06:28:27.037900Z

It's fairly common, and most large react libraries utilizes the single map pattern

emil0r 2021-01-12T06:30:56.040300Z

re-com from day8 is written with a sequence arg list. Looks pretty, but makes it a bit harder to programmatically build up props

p-himik 2021-01-12T07:52:55.041500Z

After a couple of years of using the "re-com way", I've found that using just a single map is so much better. Even if you don't change the props - just passing them through some component is both easier and simpler.

1💯
2021-01-12T11:30:17.056400Z

When designing re-com (about five years ago, when I was young and foolish) my goodness we agonized over that decision endlessly: "single map arg" vs "named args" (map vs pseudo-map). One way (map arg) would have been like this:

[button {
  :label "click me"
  :on-click #(...) 
  :disabled? false}]
vs the alternative named args (pseudo map) approach:
[button 
  :label "click me"
  :on-click #(...) 
  :disabled? false]
It was ultimately a trade-off between the ease of "prop-drilling" (single map) verses the reduced visual noise (of not needing {} because the args are a pseudo map). At the time, we felt the amount of "prop-drilling" with re-com was relatively small (because these components are leaves), whereas there is a LOT of hierarchical data structures to create and avoiding needing paired {} is a blessing. So that ended up tipping us in the named args (pseudo map) direction. That was our thought process. I still feel we did the right thing, on balance, without ever feeling 100% sure about it. But, as a general rule, you should absolutely favour a single map arg (for ease of prop drilling), unless you find compelling reasons not to.

p-himik 2021-01-12T11:36:53.059900Z

There are other (maybe minor) points to consider: - Not every editor can level the values of named args (Cursive can not, for example) - A map literal with an odd number of values will result in a compile time error, as opposed to a run time one - With a map literal, you can embed children as it's done in the rest of the React world - by adding more elements to the Hiccup vector. This, in a way, removes the noise with :children, :child, :label, and such (all from re-com)

2021-01-12T11:37:54.060300Z

All good points.

2021-01-12T11:41:55.060900Z

ooff. Our first commit to re-com was July 2014.

2021-01-12T11:42:24.061100Z

Time for re-com2?

2021-01-12T11:42:49.061500Z

And should it use tailwinds :-)

4❤️
p-himik 2021-01-12T11:43:47.061900Z

Not using Bootstrap would be nice.

2021-01-12T11:46:36.063400Z

"Utility first" CSS was the term I was searching for (tailwinds is just the latest cool kid on that block?)

2021-01-12T11:47:07.064400Z

Anyway, the latest version of re-com allows you to style all the "parts" of a component.

2👍
GusWill 2021-01-16T17:04:08.001200Z

Is the resulting css a static css file or compiled into the js bundle?

2021-01-12T11:47:14.064700Z

Should be out this week

4👍
2021-01-12T11:47:23.065Z

Small step

juhoteperi 2021-01-12T11:47:29.065200Z

For reusable components, tying it together with a CSS framework really makes it harder to use in different environments. Some React libs have solved this quite well with customizable in-JS-styles, like React-select https://react-select.com/styles

p-himik 2021-01-12T11:51:14.066300Z

Indeed. On one of the projects, I've been working with Material-UI that uses a CSS-in-JS approach. It's quite pleasant.

juhoteperi 2021-01-12T11:54:31.069100Z

Material-UI StyleProvider approach is probably definitely easier for larger component library type project. React-select requires providing the options every time component is used.

p-himik 2021-01-12T12:12:41.069500Z

Another small thing to consider - using reagent.core/class-names. It makes composing classes so much easier. Also, I'm just a fan of using keywords for classes. :)