Hi!
How can I pass static property to a Reagent component. I'm trying to reproduce persistent layout from this example:
const Home = ({ user }) => {
return (
<>
<h1>Welcome</h1>
<p>Hello {user.name}, welcome to your first Inertia app!</p>
</>
)
}
Home.layout = page => <Layout children={page} title="Welcome" />
@admin055 I’m not totally up-to-speed on modern JS and terminology. What is a static property?
This part
So Home is a function and Home.layout is another function?
Yes
What’s the point??
AFAIK you can’t add fields to Clojure Fns which is what reagent uses as functions, but why not simply have two separate functions? Why does it need to be embedded inside a JS object?
Inertia.js use it for persistent layouts https://inertiajs.com/pages#persistent-layouts and I'm trying to reproduce with Reagent.
I’m not even sure what a persistent layout even is (I’m not familiar with intertia.js), but I have a hard time seeing why it needs to be structured like that to work.
This is useful in JSX when you want to accept a generic component as children, which should implement some interface that can be accessed by getting the component type within the parent and calling its static methods
If it’s for interop with a JS library then I think that it might work like so (def MyComponent (reagent.core/reactify-component my-reagent-component)) (set! (.-layout MyComponent) (fn {} ,,,))
^^ makes sense
Thanks @josh604 for your suggestion, I try.
Since MyComponent
is now a plain React component, you would have to use the form [:> MyComponent]
. You might be able to achieve the same thing in a form-3 Reagent component using reagent.core/create-class
and calling set!
as above on the class object, inside of the form-3 function
Can someone help me with what I'm doign wrong here?
(defn test-scroll []
(let [scroll-position (reagent.core/atom 0)]
[:div
[:textarea.text-editor {:on-scroll (fn [^js e]
(js/console.log (.. e -target -scrollTop))
(reset! scroll-position (.. e -target -scrollTop)))}]
[:div (str "Scroll pos: " @scroll-position)]]))
I just want to scroll the textarea and update scroll-position when it scrolls.
When I scroll the editor, the console updates with the scrollTop value. But I think I'm doing something wrong with the atom. It always shows 0 in the test div at the end.
When I scroll the console shows this:@qmstuart If you have a stateful component it needs to be either form-2 or form-3. with-let
just allows you to make a form-2 component while skipping the inner render function, saving you a few characters and a level of indentation. I recommend reading this: https://purelyfunctional.tv/guide/reagent/
with-let
works like a form-2 component in most of the cases, but it's not entirely like it. It's a form-1 component with cache. And you can explicitly make it work differently.
yeah, i had read about form-1, form-2 then I started using re-frame and it doesn't need to the form-1, form-2 stuff and for some reason I just completely forgot that local state still needs a form-2. It just completely went out of my head 😞 I'm still learning this stuff and am definitely still in the idiot stage 😄
thanks guys
Would you say getting the scroll position of a textbox and scrolling a second text box to keep them in sync is a good use for component state ?
or would it be better as a re-frame reg-fx ?
feels like local state makes more sense.
I agree.
With an atom, you might also notice lags in scroll position synchronization. If that's an issue, you might want to combine two text boxes in a single component and sync their scrolling position via regular imperative JS.
Yeah, that's a good point. I do actually see a tiny lag... This seems to work ok though:
:on-scroll (fn [^js e]
(let [scroll-pos (.. e -target -scrollTop)]
(-> js/document
(.getElementById "lineNos")
(.-scrollTop)
(set! scroll-pos))))
Is that reasonable ?I've put both textboxes in the same component / function
(.getElementById "lineNos")
- not a great thing, impossible to reuse. Use React refs instead.
Otherwise, seems reasonable, yeah.
you mean `
React.findDOMNode(
?Nope. I mean this: https://reactjs.org/docs/refs-and-the-dom.html
thanks! I'll have a read
(reagent/with-let [ref2 (reagent/atom nil)]
[:div
[:textarea {:on-scroll (fn [^js e] (when-some [node2 @ref2] ...))}]
[:textarea {:ref #(reset! ref2 %)}]])
Replace let
with reagent.core/with-let
.
Otherwise, the ratom gets reset on each render.
thank you! that works 😄
Do I need this because I'm doing (reset!), if I was using (swap!) would I be ok with just let
?
Any change to a ratom that's deref'ed inside a view will cause that view to be re-rendered.