Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Why shallow-clj->js? #20

Closed
garrett-hopper opened this issue Feb 15, 2019 · 6 comments
Closed

Why shallow-clj->js? #20

garrett-hopper opened this issue Feb 15, 2019 · 6 comments
Labels
question Further information is requested

Comments

@garrett-hopper
Copy link

It would be nice to not have to call clj->js myself when passing in values to React components.
I assume shallow-clj->js is just a performance optimization? How significant is it?
I've found myself several times now wanting to pass a Clojure object into a React component and having to wrap it in a clj->js.

@lilactown
Copy link
Collaborator

hx makes no distinction between components defined in CLJS and components defined in JS.

If a component accepts JS objs/arrays for certain properties, you'll need to ensure you pass them in as such.

Otherwise every component defined in hx would need to recursively convert all props to CLJS structures (or use interop). You would lose metadata and benefits like easy memoization of components.

If you're doing quite a bit of interop, you could create a wrapper component that calls cljs->js for you, or even an HOC, to cut out the boilerplate.

@garrett-hopper
Copy link
Author

So even for CLJS components, their props are passed through shallow-clj->js and then shallow-js->clj for the component to use? I'm a little confused by this code. I went ahead and changed hx.react/props->clj to use js->clj and hx.utils/clj->props to use clj->js, and it fixed my problem, but I can see how that's sub-optimal when using CLJS components (losing metadata and whatnot).

@lilactown
Copy link
Collaborator

Yep, even for CLJS components, their props are passed through shallow-clj->js when parsing hiccup. defnc converts the props object to a map for you.

See: hiccup.cljs#L39, utils.cljc.

This is why you can use React components and CLJS components with exactly the same syntax; there is no distinction between them when parsing hiccup, and defnc converts the props from a JS object to a CLJS map for you for your convenience.

I don't see this as a problem; it is a tradeoff. Most components in CLJS projects are written in CLJS; hx goes farther than other libraries to help with interop with plain React components, but deeply converting props to CLJS maps and back is just where I want to draw the line.

If it helps, here's an HOC you can use to skip some of the boilerplate:

(hx.react/defn with-edn [c]
  (fn WithEdnHoc [props]
    (hx.hiccup/make-node
     c
     (-> props hx.react/props->clj clj->js) ;; deep conversion to JS
     (.-children props)))) ;; pass in children separately

@garrett-hopper
Copy link
Author

So in something like reagent this is explicitly only done when using :>, right?
I'm trying to think if there's a clean way to use both CLJS and JS components interchangeable without any sort of ugly wrapping of the component or clj->js type work on the user's side.
This issue can be closed; thanks for talking it through with me, @Lokeh.

@lilactown
Copy link
Collaborator

Yeah, I've thought about ways to "tag" components that were made with hx to differentiate them so I could do more optimizations. But it's always going to be leaky.

At the end of the day, only the dev can know what kind of props a components needs at runtime in a dynamic language like CLJS.

@pepe
Copy link

pepe commented Feb 18, 2019

Just my 2 cents. It bothered me a little at the beginning, mostly for "ideological" reasons. Now I am more happy with this approach, cause the interop with js stuff is so much easier.

@lilactown lilactown added the question Further information is requested label Mar 10, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
question Further information is requested
Projects
None yet
Development

No branches or pull requests

3 participants