Hi, I'm starting with Helix and would like to know how to convert this to cljs:
import * as React from 'react';
import * as ReactDOM from 'react-dom/client';
import { StyledEngineProvider, CssVarsProvider } from '@mui/joy/styles';
ReactDOM.createRoot(document.querySelector("#root")).render(
<React.StrictMode>
<StyledEngineProvider injectFirst>
<CssVarsProvider>
<Demo />
</CssVarsProvider>
</StyledEngineProvider>
</React.StrictMode>
);
I've tried:
(ns app.example
(:require [helix.core :refer [defnc $]]
["react" :as react]
["@mui/joy/styles" :refer (StyledEngineProvider CssVarsProvider)]))
(defnc app []
(StyledEngineProvider ; fail: not a function nor a component
(CssVarsProvider ; fail: not a function nor a component
($ Box
($ tabs)))))
;; Start your app with your favorite React renderer
(defonce root (rdom/createRoot (js/document.getElementById "app")))
(defn ^:export init []
(.render root ($ app))
(js/console.log "Running!"))Use $ to render components
thank you for the info, my main problem is not to render components created with defnc but that
(StyledEngineProvider ; fail: not a function nor a component
(CssVarsProvider ; fail: not a function nor a component
are not components πwait, it works! π I must be tired!
Glad to hear it was fixed π
thanks2
(ns app.example
(:require [helix.core :refer [defnc $]]
["react-dom/client" :as rdc]
["@mui/joy/styles" :refer [CssVarsProvider StyledEngineProvider]]))
(.render (rdc/createRoot (js/document.querySelector "#root"))
($ StyledEngineProvider {:injectFirst true}
($ CssVarsProvider
($ Demo))))
sth like this should work
I thought it would be useful to see in the browser elements panel what dom nodes map to which helix components was curious if there is interest to make a PR to add the feature to helix (see thread for code)
#?(:cljs
(defn forward-ref? [c]
(and (object? c)
(object? (g/get c "type"))
(=
(g/get (g/get c "type") "$$typeof")
(. js/Symbol for "react.forward_ref")))))
#?(:cljs
(defn dom-node? [c]
(or
(and (object? c) (string? (g/get c "type")))
(forward-ref? c))))
#?(:cljs (def component-name-attribute "data-helix-component"))
#?(:cljs
(defn apply-data-attr-to-first-child [component-name children]
(let [c (hchild/map
(fn [child]
(cond
(not (react/isValidElement child)) child
(dom-node? child)
(react/cloneElement child (js-obj component-name-attribute component-name))
(g/getValueByKeys child "props" "children")
(let [children1 (g/getValueByKeys child "props" "children")]
(react/cloneElement child #js{} (apply-data-attr-to-first-child component-name children1)))
:else
child))
children)]
(if (= (hchild/count children) 1) (first c) c))))
#?(:clj
(defn- fnc* [display-name props-bindings body]
(let [component-name (str *ns* "/" (str/replace (name display-name) "-render" ""))]
`(fn ^js/React.Element ~@(when (some? display-name) [display-name])
;; maybe-ref for react/forwardRef support
[props# maybe-ref#]
(let [~props-bindings [(helix.core/extract-cljs-props props#) maybe-ref#]
children# ~(if body `(do ~@body) [])]
(if ^boolean goog/DEBUG
(apply-data-attr-to-first-child ~component-name children#)
children#))))))
comes down to augmenting helix.core/fnc*and the result of using it:
iirc React DevTools already has similar functionality. Try selecting a DOM node then clicking the βComponentsβ tab
yes, this is for the dom, not react
I wouldn't accept this PR. React DevTools can easily go the other way, and I don't want to litter peoples apps with these extraneous data-helix-component attributes
it seems neat, and if you like to use it in your app, all the power is yours!