Fork me on GitHub
#reagent
<
2019-11-01
>
jkxyz16:11:32

@franquito You would write that component like this:

(defn main []
  (let [inner-ref (atom nil)]
    (fn []
      ^{:ref #(reset! inner-ref %)} [inner])))
There’s a guide to refs here: https://github.com/reagent-project/reagent/blob/master/doc/FAQ/UsingRefs.md

roman01la16:11:48

that’s weird, React itself should take handle of assigning refs

roman01la16:11:31

I mean yes ref can be a function, but it can be an object as well where ref target is assigned under current field.

frankitox16:11:35

Right, from the documentation I understood that for the ref to be an object you also need to use React.forwardRef. But I wanted to understand what actually happens in this particular case of ^{:ref ref} [component]. I've seen adding :key as metadata, but never :ref. About your comment @josh604 I've tried running

(defn inner []
  [:div "Hello world!"])

(defn main []
  (let [inner-ref (r/atom nil)]
    (fn []
      ^{:ref #(js/console.log "Hi?")} [inner])))
But the Hi? is never logged.

p-himik16:11:32

Judging by the source code, I'm fairly certain the Reagent respects only :key in the metadata.

👍 8
roman01la16:11:59

ha! ok, sorry for confusion

roman01la16:11:40

btw since Reagent passes all args as actual arguments you don’t need forwardRef

roman01la16:11:04

because in JS React ref prop is treated specially

jkxyz16:11:23

yeah, it seems obvious now that you can’t get a ref on a component, only on a DOM element 🙂

roman01la16:11:11

hm, I think it should be possible to refer to an instance of a component via refs

jkxyz16:11:02

according to the React docs, only on class-based components https://reactjs.org/docs/refs-and-the-dom.html

roman01la16:11:14

but again, might be not needed in Reagent, since components are functions, not classes with public APIs

roman01la16:11:55

on the other hand internally Reagent components are created as React classes 🙂

lilactown16:11:52

passing ref is confusing in React because they specifically dissoc it from props for class components. but reagent doesn’t pass in arguments as regular props, it all gets bundled into an argv prop

lilactown16:11:18

so if you give a reagent component a prop named ref it will work as you would expect

p-himik16:11:30

It seems that you can still make something interesting with metadata - Reagent passes it directly to createReactClass. But it's the metadata for a function itself - not its usage, like in [f props]. And the resulting React class becomes cached, where the function itself is the key. I.e. all usages of f must use the same metadata for the results to be predictable. Using (with-meta f) yields a different object, so the same f can be reused with different metadata.

p-himik16:11:46

Yeah, an example from the README:

(def component-with-callback
  (with-meta plain-component
    {:component-did-mount
     (fn [this]
       (reset! my-html (.-innerHTML (reagent/dom-node this))))}))
Although I definitely prefer the explicit version with create-class.

try-not-to-cry 8
dominicm18:11:52

I ended up not needing it, but I was looking at using classes internally so I could tie information about the render method back to other actions.