weavejester / hiccup

Fast library for rendering HTML in Clojure
http://weavejester.github.io/hiccup
Eclipse Public License 1.0
2.68k stars 174 forks source link

Support reagent-style form-1 and form-2 components #153

Closed mk closed 5 years ago

mk commented 5 years ago

This adds support for rendering reagent-style form-1 and form-2 components. This has enabled us to do server-side rendering for our re-frame app in Clojure and letting react take over once it's been initialized.

weavejester commented 5 years ago

Can you explain what "form-1 and form-2 components" are?

mk commented 5 years ago

Sorry, been meaning to link to the docs, see form-1 component and form-2 component.

For a form-1 component reagent only differs from hiccup in using square brackets vs parens. A form-2 component (a component returning a render function) is used when you need local component state in reagent.

There's also form-3 components in reagent which I haven't supported, but the readme states:

In my experience, you'll probably use Form-3 components less than 1% of the time, perhaps only when you want to use a js library like D3 or introduce some hand-crafted optimisations.

We've been using a hiccup fork with those two changes applied for a few weeks in production at Nextjournal now and have been pleasantly surprised how well it's worked to reuse view code between Clojure with hiccup and ClojureScript with Reagent.

weavejester commented 5 years ago

Is there a reason this should be in Hiccup itself, rather than being implemented as a transformation function?

mk commented 5 years ago

Do you mean a function that runs before the markup reaches hiccup or is there a special transformation function that's applied to each element in Hiccup that I don't know about? I hadn't really considered that up to now.

Assuming you mean the former, I guess it's for you to decide if you'd like this to be part of Hiccup. I think it could be useful to enable server-side-rendering of reagent-style markup by default. I could also see the implementation within hiccup being faster and easier.

weavejester commented 5 years ago

Do you mean a function that runs before the markup reaches hiccup or is there a special transformation function that's applied to each element in Hiccup that I don't know about?

A function that runs before the markup reaches Hiccup.

In general, solutions that are isolated from each other are better than ones that are dependant on each other. Reagent's syntax is there to integrate with React's component caching, but in Hiccup there would be no point to the syntax other than a way of being a little more compatible with Reagent. I don't think that's a good enough reason to add it.

It would also add extra conditionals to Hiccup's compiled code, slowing it down under some circumstances. Your PR doesn't account for a few different compilation edge cases, which a full solution would need to do. I think you'd be better off walking the data structure and explaning out the Reagent-specific terms, before it's passed to Hiccup.

mk commented 5 years ago

Understood, thanks for the detailed explanation and thanks a lot for all your great open source work!