This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2018-07-11
Channels
- # aleph (3)
- # beginners (42)
- # cider (219)
- # cljs-dev (39)
- # cljsjs (19)
- # cljsrn (3)
- # clojure (97)
- # clojure-canada (12)
- # clojure-dev (14)
- # clojure-italy (5)
- # clojure-nl (4)
- # clojure-russia (1)
- # clojure-spec (3)
- # clojure-uk (140)
- # clojurescript (52)
- # clojutre (2)
- # cursive (2)
- # datomic (29)
- # docs (1)
- # duct (13)
- # emacs (19)
- # fulcro (8)
- # funcool (2)
- # graphql (26)
- # hyperfiddle (1)
- # luminus (9)
- # nyc (7)
- # off-topic (26)
- # om (21)
- # onyx (19)
- # overtone (1)
- # pedestal (4)
- # re-frame (10)
- # reagent (109)
- # ring (5)
- # rum (15)
- # shadow-cljs (120)
- # spacemacs (22)
- # specter (7)
- # vim (10)
i'm working on a form library for reagent, and it uses a schema for both preparing the dynamic ratom, as well as rendering parts of the form. it was getting messy passing the schema down through everything, so i wanted to create a dynamic var and bind it using a macro. i can't seem to get the binding right though -- my knowledge of what is bound when is not very good. i have a file which does some preparation / state manipulation, where the dynamic schema is bound like:
fields.cljs
(def ^:dynamic *form-schema* {:id "unbound"})
then a clj file with the same namespace, which does the binding:
fields.clj
(defmacro with-schema [form-schema & body]
(binding [*form-schema* ~form-schema]
~@body))
in the frontend file:
(fn render-fields []
;; just for demonstration
[:h1 (:id fields/*form-schema*)]
)
when i try to use it like:
(fn render-form []
(with-schema {:id "test"}
[frontend/render-fields]))
i always get unbound
as the id returned.
any ideas?There's several components people can use -- fields, buttons, debugger for current state of form etc. Rather than pass down a map through several layers of nesting, and since the schema is always the same in the context of the form, a bound dynamic var would clean a lot of it up
does it work without the macro? i.e., if you just type out the binding? I suspect its a namespace issue
(fn render-form []
(with-schema {:id "test"}
[:h1 (:id [fields/*form-schema*])]))
works finedoes it work without the macro when using components in other files? i think it would be useful to take the macro out of the picture
(fn render-form []
(binding [fields/*form-schema* {:id "test"}]
[frontend/render-fields]))
(fn render-form [] (binding [forms/*form-schema* {:id "test"}] [frontend/render-fields]))
yeah, i use it to prepare a "live" atom state, and also to do a bunch of rendering of different components
i mean, it’s going to work in the simple example, but remember that every time you have a (fn parent [] [child blah blah]
the child
function will be run later
it's more to show that all the components are linked to the same schema in that context.
right.. timing of bindings & running of code is tricky to reason about on the front end i guess
i don’t quite understand what you want to accomplish so I’m not sure what to do to make it work for you
Right now, using the library is like:
(defn form-component [form-schema]
(let [state (formic-field/prepare-state form-schema values)]
[:div "Parent component"
[:form
[formic-frontend/fields form-schema state]
[formic-frontend/buttons form-schema state]
[formic-frontend/debug form-schema state]
]]))
But i wanted to make it like:
(defn form-component [form-schema]
(formic-field/with-schema form-schema
(let [state (formic-field/prepare-state values)]
[:div "Parent component"
[:form
[formic-frontend/fields state]
[formic-frontend/buttons state]
[formic-frontend/debug state]
]])))
To show all was bound within the same schema.Does anyone know how to achieve React.forwardRef
in reagent? https://reactjs.org/docs/forwarding-refs.html
I’m implementing ReactPopper.js using Reagent and it seems to be a sticking point based on this issue: https://github.com/FezVrasta/react-popper/issues/198
That forwardRef write-up is funny. To me it says, “Remember when we jumped up and down about component isolation? OK, that was wrong.”
Any experience/feelings on using https://github.com/mui-org/material-ui?
I've been trying to migrate away from cljs-react-material-ui, which is stuck in the v0 time. Just today I noticed that someone had made a fork for v1, but that fell on its face. So now I'm thinking if I should use material-ui directly, or perhaps these "official" react components https://github.com/material-components/material-components-web-react
I’ve been using material-ui from cljsjs. [cljsjs/material-ui "1.2.1-0"]
was added there recently.
At one point I did some experiments with ‘double bundle’ approach described here. https://clojurescript.org/guides/webpack
I was able to consume material-ui from npm
quite easily. No problems with that, but I decided to use cljsjs
anyway because it’s simpler. I thought I would use all the fancy libs from npm but I found out quite soon that in many cases it’s better to just write your own component instead of spending time learning the api and customizing the component to your needs.
I am using material-ui with webpack (I am using v1 since it was beta and it wasn't on cljsjs so it was the only option - other than figuring out how to update cljsjs package)
I've been trying to migrate away from cljs-react-material-ui, which is stuck in the v0 time. Just today I noticed that someone had made a fork for v1, but that fell on its face. So now I'm thinking if I should use material-ui directly, or perhaps these "official" react components https://github.com/material-components/material-components-web-react
@tomi.hukkalainen_slac the cljdoc formats it better https://cljdoc.xyz/d/reagent/reagent/0.8.1/doc/documentation-index
i don’t use material ui myself, but I would definitely lean towards doing direct interop instead of using a wrapper library
with shadow-cljs as your build tool, it can be easy and efficient to use the npm packages directly
@tomi.hukkalainen_slac @lee.justin.m Btw. Reagent repo has a small material-ui v1 example with just the interop: https://github.com/reagent-project/reagent/blob/master/examples/material-ui/src/example/core.cljs
Instead of adapt-react-class
, e.g. [:> mui/MenuItem ...]
would also work, without need to create def
for every component.
the example doesn't use mui-theme-provider, I'm not sure how that works, but in general it should be easy to use mui with just interop
I guess I could extend the example with some theme settings etc. to show how they work
@juhoteperi is that :>
really required or could native react components be somehow just detected (x.prototype.isReactComponent etc.)? did you think about that?
It is currently required. Reagent doesn't do detection and I have no idea if that would be possible.
since it already differentiates between keywords and fns it would feel natural for it to detect for the presense of a react component without resorting to adapting
No both adapt-react-class and :>
have same performance
reading the official React docs I don't see the function isReactComponent that is possibly there anyway
I mean those have better performance compared to detecting so no adapt-react-class or :>
like I suggested
there isn't really any conversion, well, except for parameters, but that happens in both cases
adapt-react-class
creates a Cljs type and Reagent render code has case for that type which will call react/createElement
, and :>
does the same
this was what lead me to my question https://stackoverflow.com/questions/33199959/how-to-detect-a-react-component-vs-a-react-element
I'm not sure if that helps with e.g. functional components which are just normal functions
Normal Reagent components are just functions
There is no way to see if a function is Reagent component or functional React component
also one could assume that if it's not keyword or regular (ClojureScript) fn it's a react component?
ClojureScript fn is JavaScript fn
One cljs is compiled to JS there is no way to see if the function was created from Cljs or from React lib
Yes, but in this case they don't have
i.e. (defn reagent-component [] [:div "foo"])
and function reactComponent () { return <div>foo</div>; }
create same function
IF Reagent has some def component macro like some other wrappers, we could add properties or something
so what difference does it make to [foo :bar 42]
expression in reagent if the foo is React or CLJS?
Native doesn't need to be wrapped. Native is marked using a type or :>
as it can be passed directly to React.
Reagent functions need to be wrapped in lifecycle methods which handle ratoms.
Reagent implementation is quite complex 🙂 The implementation could be much simpler if Reagent used some macros to generate components or to wrap function bodies. But that wouldn't be Reagent.
just wondering if there would have been a way to distinguish automatically and avoid the spurious :>
"syntax"
Seems like with latest Cljs it is possible to use real npm names for Material UI:
["@material-ui/core" :as mui]
["@material-ui/core/styles" :refer [createMuiTheme]]
["@material-ui/icons" :as mui-icons]
This will make it easy to later use node modules which will enable DCE for Mui.@justinlee it's not, but the wrapping issue it's part of is though, nobody maintains wrappers etc.
I'll have extensive no-wrapper Material-UI example online soon
what i’m saying is, interop is a top goal for me, but worrying about a two-character piece of syntax is literally last on the list of things that makes it hard
just getting npm packages to import correctly is hard enough. then there is the fact that reagent isn’t a straight mapping to react at all and you’ve got to learn quite a bit about it’s subtleties to get interop with more complex packages working. the :>
is easy enough
yes there are other problems, like the libs requiring JS-specific tooling to enable customization, theming etc.
@juhoteperi Hm. Then, is there any reason to use cljsjs-material-ui anymore?
https://github.com/reagent-project/reagent/blob/master/examples/material-ui/src/example/core.cljs This example now uses theme, withStyles, grid and icons
@juhoteperi that’s giving me a 404
That refers to the commented requires, with real npm module names
the current names wouldn't work with npm packages, ClojureScript compiler currently has at least two bugs:
1. preventing using of scoped npm packages with node_module support
2. foreign-libs providing and using global-exports don't with if name has @
@tomi.hukkalainen_slac you can’t use scoped packages with cljsjs either. just use the normal includes
Ah, so https://github.com/cljsjs/packages/commit/c305691f49a8ab8f2b9cdfd3828e548a99e995b2#diff-3e9f409c8bd791752004db5bf19a2beaR31 was a trick (or future proofing) 😉