Comments (14)
Ran into this today...
extracted the relevant parts from cljs-react-material-ui and it worked like a charm.
(ns app.core
(:require [sablono.util]))
(defn adapt-class [react-class]
(fn [& args]
(let [[opts children] (if (map? (first args))
[(first args) (rest args)]
[{} args])
type# (first children)]
(let [new-children (if (vector? type#)
[(sablono.interpreter/interpret children)]
children)]
(apply js/React.createElement react-class
(clj->js (sablono.util/html-to-dom-attrs opts)) new-children)))))
Would really appreciate it if an utility like this can be added to rum. It seems like a natural thing to want to do.
from rum.
Thanks for this, I adapted this for use within my Antizer library, but also added a few things:
- Changed (vector?) to (sequential?) to handle cases where child elements can be a list, eg: from a (for)
- Check properties hash-map values for any valid HTML element tags and convert them to a React element
- Sablono's
html-to-dom-attrs
function does not work for nested hash-maps, so I replaced it with a function I wrotemap-keys->camel-case
.
(require '[clojure.string :as string])
(require '[clojure.walk :as w])
(defn kebab-case->camel-case
"Converts from kebab case to camel case, eg: on-click to onClick"
[input]
(let [words (string/split input #"-")
capitalize (->> (rest words)
(map #(apply str (string/upper-case (first %)) (rest %))))]
(apply str (first words) capitalize)))
(defn map-keys->camel-case
"Stringifys all the keys of a cljs hashmap and converts them
from kebab case to camel case. If :html-props option is specified,
then rename the html properties values to their dom equivalent
before conversion"
[data & {:keys [html-props]}]
(let [convert-to-camel (fn [[key value]]
[(kebab-case->camel-case (name key)) value])]
(w/postwalk (fn [x]
(if (map? x)
(let [new-map (if html-props
(rename-keys x {:class :className :for :htmlFor})
x)]
(into {} (map convert-to-camel new-map)))
x))
data)))
(defn adapt-class [react-class & args]
(let [[opts children] (if (map? (first args))
[(first args) (rest args)]
[{} args])
type# (first children)
;; we have to make sure to check if the children is sequential
;; as a list can be returned, eg: from a (for)
new-children (if (sequential? type#)
[(sablono.interpreter/interpret children)]
children)
;; convert any options key value to a react element, if
;; a valid html element tag is used, using sablono
vector->react-elems (fn [[key val]]
(if (sequential? val)
[key (sablono.interpreter/interpret val)]
[key val]))
new-options (into {} (map vector->react-elems opts))]
(apply js/React.createElement react-class
;; sablono html-to-dom-attrs does not work for nested hash-maps
(clj->js (map-keys->camel-case new-options :html-props true))
new-children)))
from rum.
Maybe... I'm not a fan of that cryptic stuff (hard to search for, hard to understand if you're seeing it for the first time). I'd prefer something like (def Comp (rum/pour js/Component))
(adapt-class
I mean :)).
from rum.
@abhishiv have you solved this?
from rum.
I had no problem using a react-treeview component with rum. May be worth mentioning that rum is compatible w/ react components. I know that quiescent does
from rum.
Actually, since we are going to fork Sablono I'm more into introducing [:> js/Component props & children]
syntax, similar to Reagent
from rum.
Fixed in 3938ac1
from rum.
When you write [(.-Route js/ReactRouter) {:name "home"} ]
sablono tries to parse it as tag, something of form [:div attrs & children]
.
Just create component with interop syntax, e.g. (js/ReactRouter.Route #js {:name "home"})
. Do not put in a vector as first element (but as child β in sablono terms β itβs ok)
from rum.
Is there an easy way to compose external react components, like say js/ReactBootstrap.ModalDialog?
I've only been able to create external react components with a (js/React.createElement js/ReactBootstrap.Button (clj->js args) content) command, which is not composable. I know in Reagent, you can just say [ReactBootstrap.Button args "label"]
from rum.
I think this could be clear in docs. Reagent has a function to adapt class, and I saw something similar in a cljs-material-ui wrapper, "adapt-rum-class" (https://github.com/madvas/cljs-react-material-ui/blob/f66e8047b556e41dce45b1391cae9ca13f25242f/src/cljs_react_material_ui/core.clj). Is it needed?
from rum.
@priornix 's solution above has the problem where any data prop you pass in to the component, if it's in the form of a hash-map, will get keys mangled.
from rum.
We'll probably introduce something like this. @piranha @martinklepsch Do you have anything like that in your code?
from rum.
We don't have a lot of external React components and for those we have integration is just some custom code. We used antizer in Suppliers UI though and I didn't touch that for a while, but I think it worked well. :) And we have more external deps there.
from rum.
I'm perhaps biased since I'm using Reagent now and it feels good to be able to use JS components inline, w/o making another def using class adapter. But I'm also fine with going both ways.
from rum.
Related Issues (20)
- rum/fragment with React components HOT 2
- optimizations :advanced (shadow-cljs) failing on simple :form :input
- defc error with shadow-cljs. Makes Rum unusable for me... :( HOT 22
- daiquiri: fragment? fails on vectors HOT 13
- Question about rendering performance when updating state asynchronously HOT 9
- should-update error
- Big performance regression between 0.11.5 and 0.12.3 HOT 9
- Server/client difference when rendering nil HOT 2
- require-lazy macro unnecessarily prescriptive about namespace/module structure HOT 1
- Error when use `rum/local` and `rum/use-callback` together HOT 2
- Hydration not fully compatible with React 18 HOT 4
- bind-context produces unfixable infer warnings HOT 3
- `with-key` and `with-ref` Removing children? HOT 2
- ClojureScript >=1.11.51 seems to break Rum HOT 4
- ClojureScript >=1.11.51 seems to break Rum HOT 3
- How to use daiquiri.core/html ? HOT 9
- How can I use npm based react library I rum ssr mode HOT 4
- Live Examples Missing HOT 1
- Hulunote(a tool for networked thought) use the rumπ
- Interpretation warnings print var symbol instead of the value
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
π Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. πππ
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google β€οΈ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from rum.