Fork me on GitHub
#re-frame
<
2016-11-10
>
oliy16:11:07

hi, does anyone have any tricks they use for re-rendering a component when its size changes?

oliy16:11:02

context: i'm drawing an svg which takes width and height to make it fill its container. the container is a cell in a material grid, so it will resize when the window resizes

oliy16:11:13

i can use r/track for the window size, but not the component size (because i don't have a dom element to track outside the lifecycle methods)

akiroz17:11:20

@oliy Couldn't you just re-render on screen resize?

oliy17:11:27

force a re-render you mean? and calculate the size within the render method?

oliy17:11:14

@akiroz i was hoping there was a way i could run a function which would take "this" (like lifecycle methods get) and push the new dimensions into a ratom

oliy17:11:58

i could add that as an event listener on the window but then i'm not sure how to unlisten when the component is unmounted,

akiroz17:11:06

@oliy with re-frame, you probably want an event handler that runs on screen resize, and pushes your element's dimensions into the app-db then you'd have your component subscribe to that dimension and render accordingly

mattly17:11:33

I'm playing around with making window width a cofx

oliy17:11:00

the problem with that @akiroz is that i don't have a reference to the component's dom node (which i need to measure to get the dimensions) in a generic event handler

mccraigmccraig18:11:08

@oliy with a type-3 component you can get and keep a reference to the DOM node in :component-did-mount

mccraigmccraig18:11:38

:component-did-mount (fn [ref] (let [dn (reagent/dom-node ref)] ... ))

akiroz18:11:33

@oliy Um... I think you can attach the window resize handler inside your type-3 component and pass a ref to the re-frame event handler using a closure:

:component-did-mount
(fn [this]
  (.addEventListener js/window "resize"
    #(dispatch [:window-resize (reagent/dom-node this)])))

akiroz18:11:33

but you may have to clean up the event handler when your component unmounts

oliy18:11:19

@akiroz i think when you came to unlisten on unmount it would be a different function (not equal to the original in component-did-mount

{:component-did-mount
(fn [this]
  (.addEventListener js/window "resize"
    #(dispatch [:window-resize (reagent/dom-node this)])))
 :component-will-unmount
 (fn [this]
  (.removeEventListener js/window "resize"
    #(dispatch [:window-resize (reagent/dom-node this)]))) ;; <-- this anon. fn is not the same as the one above
}

akiroz18:11:11

yeah, you might have to put that function somewhere else.

oliy18:11:45

i'd still need to partial it with this and i think i'd have the same problem

oliy18:11:18

well, i wouldn't have this outside the closure

akiroz18:11:22

right.... that wouldn't work...

mccraigmccraig18:11:48

@oliy (let [owr (fn [e] ...) dn (atom nil)] {:component-did-mount (fn [ref] (reset! dn (reagent/dom-node ref) (.addEventListener js/window owr)) ... })

oliy18:11:55

that seems a bit evil @mccraigmccraig, don't you think?

oliy18:11:15

or, unidiomatic at least 🙂

oliy18:11:32

i considered that but i thought there must be a better way...

mccraigmccraig18:11:58

which bit are you thinking is evil ?

oliy18:11:13

storing the dom-node in a local state atom

oliy18:11:25

doesn't feel very react-y

akiroz18:11:10

lol don't react people use this.setState() for pretty much everything? xD

mccraigmccraig18:11:19

well you are going to have to store it somewhere for times when you don't have access to the ref

oliy18:11:44

i looked at reagent.impl.component/*current-component* but it wasn't bound when i called it, that also feels like i should steer clear of it

mccraigmccraig18:11:12

if you don't need it in the render i imagine you can use reagent/dom-node in the other callbacks which do get the this

akiroz18:11:16

I guess every framework has a few corner use cases... I've been scratching my head for a few days a while back when I have some derrived state that I need to access in both my view and events.

oliy18:11:23

ok thanks guys you've given me some ideas

Pablo Fernandez19:11:40

When designing an API, on a validation error or some other kind of rejection, do you return a 200 or a 400? 400s seems more appropriate, but in a re-frame app, 200s call one function while 400s and 500s call another, which means that two expected paths are broken apart and one is mixed with an exceptional path.

mccraigmccraig19:11:22

i thought about this for a minute @pupeno then realised i do all my validation client-side and am ok with any validation failures from the API being handled as errors

Pablo Fernandez19:11:08

mccraigmccraig how do you validate the uniqueness of an email on the client?

mccraigmccraig19:11:50

ask the server!

mccraigmccraig19:11:39

but, i do have some cases where i return status inside a 200 response

mccraigmccraig19:11:30

e.g. if an email fails to send for some upstream reason that will return a description of the failure in a 200

Pablo Fernandez19:11:48

ok, so you return errors (not exceptions) in a 200.

Pablo Fernandez19:11:10

Whether they are rare or not, the code to deal with them has to exist, so, their frequency is not important.

mccraigmccraig19:11:19

when the client is expected to be able to deal with them as part of normal flow, yes

akiroz19:11:58

@pupeno It really depends if you need a REST complient API... Most of my servers has a single web-socket endpoint and a fallback HTTP endpoint.

akiroz19:11:20

This way, your client can be more flexable about what it's allowd to ask for even if you don't use fancy stuff like graphQL

Pablo Fernandez19:11:44

I don’t need to be REST compliant. I’m writing both the client and the servere.