This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2015-09-14
Channels
- # admin-announcements (5)
- # alda (2)
- # beginners (26)
- # boot (30)
- # cider (8)
- # clojure (49)
- # clojure-argentina (1)
- # clojure-berlin (1)
- # clojure-boston (1)
- # clojure-italy (11)
- # clojure-norway (3)
- # clojure-russia (116)
- # clojurescript (156)
- # clojurex (4)
- # clojutre (9)
- # core-async (6)
- # datomic (18)
- # emacs (1)
- # events (4)
- # hoplon (159)
- # ldnclj (13)
- # luminus (4)
- # off-topic (1)
- # re-frame (14)
- # reagent (76)
Haven't used it yet, but reagent-forms has a typeahead: https://github.com/reagent-project/reagent-forms
I've got a question about the React methods when using create-class
.
If I have a component which accepts multiple parameters how can I tell which parameter was updated in a call to :component-did-update
?
component-did-update
passes has a signature of [this old-argv]
, but where can i get the new-argv
to compare
For example, in the following code, I want to put ***
next to the val which was last updated:
(defn a-component [val1 val2]
(let [last-updated (r/atom -1)]
(r/create-class
{:component-did-update (fn [this old-argv]
; how do I find out if val1 was the cause of the update?
#_(if (????)
(reset! last-updated 1)
(reset! last-updated 2)))
:reagent-render (fn [val1 val2]
[:div
; display the current value of each,
; and indicate which was last updated
[:div (str "val1 " val1 (when (= 1 @last-updated) " ***"))]
[:div (str "val2 " val2 (when (= 2 @last-updated) " ***"))]])})))
(defn wrapper []
(let [v1 (r/atom 0)
v2 (r/atom 0)]
(fn []
[:div
[:button {:on-click #(swap! v1 inc)} "Inc 1"]
[:button {:on-click #(swap! v2 inc)} "Inc 2"]
[a-component @v1 @v2]])))
I'm not sure what to put in the component-did-update
to determine which parameter caused the update.
Thanks. I'm really looking for a way to respond to the update in the a-component
however. I want my component to be smart enough to know when it needs to reset some local state.
I mean, I could create local atoms just to store the most recent versions of each parameter, then I'd have the prior value from that and the new value from component-will-update
, but I feel like there should be a better way.
I looking more into the React lifecycle, and it sounds like maybe what I want to use is component-will-receive-props
, but when I try to get the props out, all I get is nil:
:component-will-receive-props (fn [this new-argv]
(println "WILL RECEIVE PROPS")
(println "OLD" (r/props this)) ;always nil :(
(println "NEW" new-argv))
Haven't used these, but this might be a section worth looking at in reagent: https://github.com/reagent-project/reagent/blob/b77b182d67276706d47b138b0374f7841e1d58b9/src/reagent/impl/util.cljs#L9
yeah, I did try that, same result. It looks like that's where (core/props) calls into
thanks @gadfly361 for the help
yeah, seems so. And this is great!! Thank you for figuring this out. Gotta save this example.
I'm going to re-post @sashton 's snippet inline (rather than as a attechment) so it gets properly archived at: http://clojurians-log.mantike.pro/reagent/2015-09-14.html Otherwise it might be lost:
(defn a-component [val1 val2]
(let [last-updated (r/atom -1)]
(r/create-class
{:component-will-update (fn [this new-argv]
(let [[_ old-v1 old-v2] (rutil/get-argv this)
[_ new-v1 new-v2] new-argv]
(reset! last-updated
(cond
(> new-v1 old-v1) 1
(> new-v2 old-v2) 2
:else 0))))
:reagent-render (fn [val1 val2]
[:div
; display the current value of each,
; and indicate which was last updated
[:div (str "val1 " val1 (when (= 1 @last-updated) " ***"))]
[:div (str "val2 " val2 (when (= 2 @last-updated) " ***"))]])})))
(defn wrapper []
(let [v1 (r/atom 0)
v2 (r/atom 0)]
(fn []
[:div
[:button {:on-click #(swap! v1 inc)} "Inc 1"]
[:button {:on-click #(swap! v2 inc)} "Inc 2"]
[a-component @v1 @v2]])))
Thanks @mikethompson, I'll also add an example to https://github.com/reagent-project/reagent-cookbook later this week
I'm having trouble wrapping my head around the right linkages... I have a textarea tied to a ratom, and I'd like to update the :rows
attribute (also tied to a ratom) on it based on the contents (i.e., autoresize). I can get it to update the ratom fine with onChange, but how do I get the resize to run when I change the text externally?
but now I have a different problem... I can't figure out why my :on-click
isn't making it through:
(defn items []
(let [visible? (r/atom false)]
[:div
[:h4 {:on-click #(swap! visible? not)} "Items"]
[:table {:style {:display (if @visible? "block" "none")}}
;; table stuff here ]]]))
oh... hmmm. actually, reagent is picking up the click (i.e. it's not on the element directly) but the component doesn't rerender.
Also - react doesn't really generate onClick
handlers it lets all event bubble up and only then dispatches it's synthetic events and reacts to that. If you want to inspect handlers you need to use react devtools for chrome.
thanks, that's helpful to know. it also helps explain why the attribute is :on-click
!
now I just have to build the same component 3x for the different backing collections.
No, the :on-click
gets translated to onClick
anyway (om for example uses the original React casing), it's just that React's virtual DOM implementation doesn't hang the handlers on the real DOM, just deals with it internally.
how would you create elements dynamically inside a component? I'm doing something like this:
[:tr
(for [k (keys colmap)]
[:th k])]
they both work. my idea was to create a generic component that does the hide/unhide toggle, and pass in the params it needs to get the right stuff out of the ratom.
but it's very warn-y. I get warnings about returning false from an event handler, and every element in the seq needing a unique key (doesn't like lots of :th in a single seq).
Yeah, you shouldn't return false
but do (fn [e] ... (.preventDeafult e))
in the handler and keys are (I think) mainly for performance optimisation, so React knows when it should insert new DOM node and when it can reuse the existing one.
:on-click (fn [e] (swap! ...) (.preventDefault e))
is how the handler should look to avoid the warning
i've got a wrapper to handle the react key generation in some of my stuff:
(defn with-react-keys
"Creates a lazy-list of reagent components with React keys
key-fn: Returns React the key for the element. (fn [item index] )
f: React component to render the item (fn [item] [:div ...])
coll: Collection of items
args: Any other args to be passed to the React component"
[key-fn f coll & args]
(if (satisfies? IAtom coll)
(for [i (range (count @coll))
:let [x (rc/cursor coll [i])]]
(with-meta (into [f x] args)
{:key (key-fn x i)}))
(map-indexed
(fn [i x]
(with-meta (into [f x] args)
{:key (key-fn x i)}))
coll)))