re-frame

https://github.com/Day8/re-frame/blob/master/docs/README.md https://github.com/Day8/re-frame/blob/master/docs/External-Resources.md
rberger 2020-07-02T00:17:54.227100Z

There’s a really nice tutorial on framer-motion (for React) at https://www.youtube.com/playlist?list=PL4cUxeGkcC9iHDnQfTHEVVceOEBsOf07i framer-motion is pretty powerful but seems to require to use it at the bottom of the component hierarchy (i.e. motion implementation of html tags like motion.div, motion.button etc) I did find that at least for simple things so far, can wrap a reagent component into a motion.div and the animate of the motion.div animates the reagent component.

bringe 2020-07-02T02:10:35.232300Z

Hello, got a quick question. I've been learning re-frame lately and came across a scenario in my app where I want to call .focus on an html element that only appears in the dom after an event (registered with reg-event-fx) is handled. I made the call to focus the element an event with reg-event-fx and used a dispatch effect in the causal event with the ^:flush-dom metadata on the event vector to make sure the element is rendered before .focus is called. If it weren't for needing that flush though, I would just use reg-fx. Is there no way to flush the dom before an effect registered with reg-fx is run?

bringe 2020-07-02T02:12:34.232400Z

Here's the code. If it weren't for needing to make sure the dom was rendered before ::focus-html-element , I would just use reg-fx to register it, because I'm not changing the db or returning any effects. Just wondering if this is idiomatic I guess.

2020-07-02T02:17:58.233400Z

To avoid complications, you could perhaps use the auto-focus attribute?

(defn view 
  []
  [:input {:type "text" :id "fname" :auto-focus true])
This only works once, when the widget is first rendered which may not give enough control, but it sure is simpler.

bringe 2020-07-02T16:14:01.245200Z

Ah, thanks! I was not aware of this.

2020-07-02T02:32:16.238Z

Also I think it doesn't work in Safari which is sadly IE of the current time 😞

2020-07-02T02:33:04.238200Z

If that doesn't give you enough control, you could create an effect which hooks into Reagent's after-render

2020-07-02T02:36:23.240600Z

(reg-fx 
  :focus-html-element
  (fn [element-id] 
     (reagent/after-render  #(some-> js/document (.getElementById element-id) .focus)))

πŸ‘ 1
bringe 2020-07-02T17:19:01.246600Z

This gave me the control+simplicity I was looking for. πŸŽ‰

2020-07-02T02:36:58.241Z

Note the use of some-> to avoid any weird corner cases

rap1ds 2020-07-02T06:18:13.243500Z

@brandon.ringe I tend to leave re-frame out of that type of very view specific logic / close to DOM and use Reagent Form-3 components for that. Something like this should do the trick:

(defn focus-input []
  (let [ref (atom nil)]
    (r/create-class
     {:component-did-mount
      (fn [_]
        (.focus @ref))

      :reagent-render
      (fn [_]
        [:input {:ref #(reset! ref %)}])})))

πŸ‘ 1
bringe 2020-07-02T16:20:03.246300Z

Interesting, this looks possibly more efficient than the .getElementById method since it avoids the lookup. Maybe not significant, but still.

2020-07-02T08:06:48.244300Z

πŸ‘

bringe 2020-07-02T16:16:14.245900Z

Thanks for all the info! Great solutions

shaun-mahood 2020-07-02T23:53:07.249600Z

@brandon.ringe Here’s one more that should work - if you want to use it and have trouble let me know and I’ll double check (writing code on my phone is not always a good idea) [:input {:ref #(when % (.focus %))}]

πŸ‘ 2
bringe 2020-07-02T23:56:23.249900Z

Thanks