This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2017-02-13
Channels
- # bangalore-clj (1)
- # beginners (29)
- # boot (13)
- # braveandtrue (5)
- # clara (5)
- # cljs-dev (42)
- # cljsrn (7)
- # clojure (55)
- # clojure-france (46)
- # clojure-nl (11)
- # clojure-portugal (1)
- # clojure-russia (268)
- # clojure-spec (26)
- # clojure-uk (32)
- # clojurescript (173)
- # clr (2)
- # core-async (46)
- # cursive (22)
- # datomic (33)
- # devcards (1)
- # emacs (5)
- # events (8)
- # figwheel (2)
- # flambo (4)
- # instaparse (8)
- # jobs (11)
- # klipse (46)
- # lein-figwheel (3)
- # london-clojurians (2)
- # nrepl (1)
- # off-topic (29)
- # om (4)
- # om-next (8)
- # pedestal (3)
- # rdf (4)
- # re-frame (51)
- # reagent (104)
- # remote-jobs (1)
- # rum (4)
- # schema (2)
- # specter (19)
- # untangled (16)
- # vim (52)
Is there a way to test if something is a reagent component? as in (reagent-component? value)
Pupeno, I think it's easier to answer that question if you give some context
@pupeno havent used this, but wonder if this is true to its name https://github.com/reagent-project/reagent/blob/b65afde4d7ac4864d7e355acdc16977cb92afa3c/src/reagent/impl/component.cljs#L62
I am making a wrapper for React Toolbox and it takes properties that can be strings or react components. My wrapper will take strings or reagent components. When it's a reagent component, I need to wrap it with as-element
https://github.com/dashmantech/reagent-toolbox/blob/master/src/cljs/reagent_toolbox/core.cljs#L16
@gadfly361 thanks. I'll look into that when I get back home.
the question is, what is a component?
do you mean the clj data structure describing the component?
or the React "backing instance"?
or the React element?
Well, I don't want to have to answer that question.
What I want to know if I'm getting a value that I need to wrap in as-element for it to be a valid react component.
why not just say
if it's a string, use it as a string
otherwise a component?
Well, that's what I'm doing right now.
that seems unmagical
But I don't know when it'll fail. Maybe another component will take numbers, so, I'll have to white list numbers.
And the white lists will keep on growing.
yeah I think this may be a sign that you should rethink the API design
not sure about that obviously
but in my experience, if your API accepts two kinds of values, it's good to be crystal clear about their boundaries
And if someone passes an already react component it will fail. So they'll have to wrap it as reagent to be re-wrapped as react.
yeah I think it's not a good idea to be more magical than reagent
I'd aim for the same (well-understood) level of magic 🙂
if that makes sense?
of course it's your api to design
I disagree there's an API design problem here. But I'm curious if you have an opinion how the API should look like.
I'm just thinly wrapping React Toolbox.
can you give an example of a component that accepts one of these either/ors?
About magical, I'm just trying to be unsurprising to users.
Example, sure:
[autocomplete {:label "Label"}] or [autocomplete {:label [:b "Label"]}]
but both of these are valid inputs to as-element
right?
hm or maybe not
I actually haven't tried it. If they are... This would be embarrassing
let's try in klipse 🙂
I've recently converted to klipse-advocate
@pupeno why not have the user wrap [:b "label"] with as-element? I feel like it is an easy thing to hand over, and will avoid white listing or unintended restrictions
That's the decision i just made with soda-ash anyways: https://github.com/gadfly361/soda-ash
@gadfly361 because I think that's not a very friendly API and it doesn't follow the React Toolbox API.
yeah bare strings are not elements you're right @pupeno
IMO the value should always be a fn
so #(as-element [:div "sdf"])
that's how most React proper APIs work
you could add a special case for strings
I thought that might be the case and then I forgot. I'll also look into that when I get home.
as a convenience for the user
Yes, I have a special case for strings right now, but I'd like to reverse that and have a special case for React components and leave everything else as is. It would be a more correct solution if it's doable.
so {:label "sdf"}
would be equivalent to {:label #(as-element [:span "sdf"])}
Because in the Reagent Toolbox API strings are not special, reagent components are special and need wrapping when you hand them over to the React world.
Oh, I can pass strings directly to react toolbox, it takes strings.
can you point me to the React Toolbox API docs section?
Sure, just a sec.
as a user, what I look for in wrappers is something as close as possible to the original, so I can use the knowledge about the original
and crucially its docs
ah label is string or node
That's sort of what I'm building. And for me, as close as possible means, if the original takes string or react component, the Reagent one should take string or reagent component.
agree
well or react component
Right. That's why I think reagent component is the special case and not string.
the whole Reagent component v React component distinction is unfortunate
Right now my code would barf if you give it a react component.
Which I guess is not a huge problem, but I'm a perfectionist.
it's going to be react components under the hood though
And by the way, I'm building a clone of that website for ClojureScript/Reagent: https://github.com/dashmantech/reagent-toolbox-playground
so accepting React components by default would be closer to how it works under the hood
Yes, that's why I think a react component should end up wrapped into a reagent one wrapped into a react one.
https://github.com/react-toolbox/react-toolbox/blob/dev/components/input/Input.js#L208
here's how it works in React Toolbox
they just add the label as a child of the <label>
tag
a child can be either a node or a string
a node being .. a React Element I guess
Yeah... I'm guessing that.
I think really the problem is that the conceptual distinction between different notions of "component" is not clear
which is reflected by the fact that people keep using different names
I agree.
so really what you want is not to accept a component but an element I guess?
I mean an element in React is just a javascript value
that looks like this:
{
type : string | class,
props : { children, className, etc. },
key : string | boolean | number | null,
ref : string | null
}
so really that's the equivalent of reagent's vectors
[:ul [:li "a"] [:li "b"]]
is a homologue of a nested React element
except much better 🙂
Here's what (r/as-element [:ul [:li "a"] [:li "b"]])
looks like:
#js {:$$typeof "Symbol(react.element)", :type "ul", :key nil, :ref nil, :props #js {:children #js [#js {:$$typeof "Symbol(react.element)", :type "li", :key nil, :ref nil, :props #js {:children "a"}, :_owner nil} #js {:$$typeof "Symbol(react.element)", :type "li", :key nil, :ref nil, :props #js {:children "b"}, :_owner nil}]}, :_owner nil}
so by that reasoning, you could say, if it's a vector, wrap it in as-element, otherwise wrap it in #(r/as-element [:span %])
I don't think all reagent components are vectors. Are they?
@tomaas you should call both with [ ... ]
. If you are experiencing option1 working with ( ... )
it is because it is nested within another component. And yes, use option 1 unless you have setup stuff to do
thank you @gadfly361
If you havent seen these yet, here are a couple useful links: https://github.com/Day8/re-frame/wiki/Using-%5B%5D-instead-of-%28%29
Which can be followed by other doubts: "if I don't understand this, what else don't I know?", which can lead to "do I really understand ANYTHING?"
@gadfly361 I'm suprised that your modal3 doesn't work
is that because Modal expects a single child component which is a Button?
I guess because it reaches into the child and attaches a on-click handler or something?
that would explain why 4 works - it results in the same React Element hierarchy as modal1
Hi! I need some suggestions on how to (easily) implement draggable/sortable list of rows in Reagent akin to this demo - https://react-dnd.github.io/react-dnd/examples-sortable-simple.html. I'd like to avoid dealing with JS libs directly if possible, so the simplest solution is probably to use https://github.com/cljsjs/packages/tree/master/react-reorderable, but the underlying JS library is deprecated.
@pesterhazy Modal, doesn't expect a button as the trigger - you can put any arbitrary element in there such as a div. And yeah, you're right, 1 and 4 are effectively the same. I was surprised when 3 didnt work too
following my question, guess I'll start with dragula
from cljsjs
, seems easy enough to integrate:
(defn -view-mounted
[this]
(let [drake (js/dragula (clj->js [(r/dom-node this)]))]
(.on drake "drop" (fn on-drop
; el was dropped into target before a sibling element, and originally came from source
[el target source sibling]
(.log js/console "New element index:"
(.call
(.. js/Array -prototype -indexOf)
(.. el -parentNode -children)
el))))))
(defn view
[]
(r/create-class
{:component-did-mount -view-mounted
:reagent-render -view}))