Fork me on GitHub
#reagent
<
2018-03-16
>
juliobarros06:03:22

Anybody have thoughts on kee-frame? It seems to be a Keechma inspired routing/controller approach on top of re-frame https://github.com/ingesolvoll/kee-frame

borkdude10:03:28

But one issue we run into with higher order components is when the child component has arguments itself which it needs to re-render

justinlee15:03:17

@borkdude I’m not sure I follow what the issue is. Is the problem that you can’t pass the arguments through the hoc?

borkdude15:03:22

It’s hard to explain without reproducing this into an issue I guess.

borkdude10:03:52

and when the parent container is a form-2 component this sometimes causes headaches

borkdude10:03:25

In the article only child components of zero args are used. Is there documentation on how to deal with this problem?

borkdude10:03:50

one solution would be to do it all with re-frame subscriptions and reduce the child component to a zero arg one

borkdude12:03:17

@tomaas I would probably debounce the reset function

borkdude12:03:29

the on-change function

pesterhazy15:03:02

@tomaas, very common problem

pesterhazy15:03:22

basically input element are a never-ending source of issues with Reagent (and to a lesser extent, React and React Native)

pesterhazy15:03:37

... if you don't need to change the value programmatically, you can also use :default-value instead of :value (use an uncontrolled component)

justinlee15:03:48

that’s weird. i though reagent wrapped input elements specifically so that the dom got updated synchronously from the on-change handler. if it doesn’t do that then the cursor jumps around and it starts dropping characters.

pesterhazy15:03:15

@lee.justin.m but how would that possible work with :value (suppose the handler function doesn't "accept" the change)

justinlee15:03:14

@pesterhazy I thought that it does some magic to ensure that the value gets updates right away. Let me take a look so I don’t say things that are wrong. I think the actual problem here is just that tomaas’s last render takes so long that the UI can’t update the input change.

pesterhazy15:03:37

yes there is magic in the reagent source

pesterhazy15:03:52

but it doesn't account for all possibilites

justinlee15:03:54

if you yield back to the event loop in between changing the atom and changing the dom, all hell breaks loose

pesterhazy15:03:04

in my experience at least

justinlee15:03:25

because if you do that, another event can come in with the old value of the dom and then a keypress gets dropped

exit215:03:19

Whats a popular server side for reagent apps? We are using cljs.nodejs but I wonder if some other native clj server side lib would be better

pesterhazy15:03:43

@lee.justin.m I'd love to understand fully what's happening. I feel I'm 80% there, but the remaining 20% are still causing trouble

pesterhazy15:03:26

the problem occurs especially when you use 3rd party input components (other React libs that wrap <Input>)

pesterhazy15:03:29

(I'm guessing because Reagent can't guess it's an input element)

justinlee15:03:56

Well if a third party wraps it, reagent won’t do anything special with it at all.

justinlee15:03:21

Reagent only does its magic if something feeds it a vector where the first element is ‘input’

justinlee15:03:03

And really you shouldn’t have this problem because you won’t be messing with reagent’s atoms if it is in a third party

pesterhazy15:03:15

all I know is that (awfully complex) piece of code doesn't work in all cases

pesterhazy15:03:10

and yes the problem occurs because of ratoms, which are batched and postponed until the next tick

justinlee15:03:03

there is more than one quirk they are dealing with. the most important one to understand is that when you press a key in an input, the next event contains the new value of the input element (not just the keypress), but does not change the dom. so most of the magic is designed to ensure that the dom gets updated in the same event. there is also an i.e. bug that is quite difficult to understand, but it basically results in a late on-change event.

justinlee15:03:42

i’d be curious to look at interactions with other libraries

justinlee15:03:46

(that don’t work)

justinlee15:03:42

@njj Do you mean serving compiled code or do you mean doing server-side rendering? If the former, I don’t think there is anything specific to reagent that matters: you can serve from jetty or node. It probably just depends on what your backend api server is on. (I have a JS backend so I server the front end bundle from node.)

justinlee15:03:02

@pesterhazy at any rate, I still suspect that there’s no real way to fix the problem tomaas is describing: I am pretty sure that if a render takes, say, 1 second to finish, the user input is going to lag no matter what. debouncing will help, but not solve, this problem

pesterhazy15:03:06

@lee.justin.m, there's also the problem that, if you add a buffer that gets updated before the proper ratom can, you have two sources of truth, and you need to decide which is authoritative

pesterhazy15:03:45

it's a tricky issue, if you want to be able to change the content of the input field programatically while it is mounted

justinlee15:03:30

oh yea that would be very gross given that you could change the input value while a change event was in flight

pesterhazy15:03:14

I almost lean towards using :default-value and changing the input field manually when necessary (if you need to clear it for example)

pesterhazy15:03:53

using default-value, @tomaas's problem should be fixable for sure

justinlee15:03:18

will the browser update the input value even if the main render thread is blocked?

pesterhazy15:03:36

yes, I think so

justinlee15:03:44

i’ve never tried

pesterhazy15:03:45

(no javascript involved)

justinlee15:03:17

@borkdude I’m not sure I follow what the issue is. Is the problem that you can’t pass the arguments through the hoc?

mikerod16:03:21

@lee.justin.m @pesterhazy I like the conversation on this. I have struggled with this before

mikerod16:03:33

and I thought it was “fixed” mostly, but occasionally I run into problems

mikerod16:03:47

I have one right now with a autocomplete sort of search integration I have

mikerod16:03:56

it loses key presses, uses foreign js libs etc

pesterhazy16:03:59

honestly I think every Reagent user with a somewhat complex app runs into issues with input components sooner or later

mikerod16:03:00

probably slipping by reagent

mikerod16:03:24

I need to fix my problem actually. I have put it off for a few because I have fought with it before and it is a time sink

pesterhazy16:03:51

yeah react-select would be one example of a 3rd party lib that might expose this problem

mikerod16:03:54

I just… want… to… understand… what is going on… 😛

mikerod16:03:09

I’ve used react-select and have had good luck I think, oddly enough

pesterhazy16:03:17

it's an amazing library

pesterhazy16:03:29

very polished

pesterhazy16:03:43

if you put up a minimal repro, we could have a look together

pesterhazy16:03:56

I also want to get to the bottom of this, maybe blog about it

pesterhazy16:03:40

I wonder if people using redux (rather than component local state) are facing the same issues

mikerod16:03:56

I thought I mostly understood the problem, but everytime I think I understand i end up not really

mikerod16:03:05

yeah, maybe I can recreate this in the small

mikerod16:03:06

will see about that

mikerod16:03:47

I have 2 libs involved in my case though, react-debounce-input and react-autosuggest

mikerod16:03:50

so it’s a pretty nasty case I think

mikerod16:03:03

the input component gets buried down in the react-debounce-input etc

mikerod16:03:29

I may be better off just abandoning that combination for what I was doing here. However, I still just in general like to try to under what is going on

pesterhazy16:03:33

yeah that might even be a problem with the React libs

pesterhazy16:03:00

I imagine there's nothing special (except for ratoms) in Reagent that causes these delays

justinlee16:03:11

I definitely ran into this issue when using redux, but I think it was just user error. There are bugs like this that are disconcerting: https://github.com/reactjs/react-redux/issues/525

justinlee16:03:19

And then there’s this ridiculous I.E. bug: https://github.com/facebook/react/issues/7027

pesterhazy16:03:48

@lee.justin.m thanks for the pointers. There's a whole cluster of different issues there, hard to disentangle

mikerod16:03:11

I think I’ve looked through all of those issues before

mikerod16:03:20

probably will need a refresher by reading them again though

mikerod16:03:43

I’ve been on websites out in the wild where I saw this behavior and I was pretty sure they were using react hah

mikerod16:03:07

Perhaps everyone should just start typing slower into input fields - problem solved 😛

justinlee16:03:59

to tell you the truth, setting aside the i.e. bug, most of the issues I’ve read that had any clear information about this all seemed to be the same issue: don’t yield to the event loop before updating node.value. I suspect that any library that tries to update an input element with intervening events is going to be very hard to get right

mikerod16:03:02

I believe that makes sense

pesterhazy16:03:22

I agree, but there are different reasons why the value is not updated fast enough

justinlee16:03:58

I don’t think it needs to be “fast”. I think it needs to be “synchronous”.

pesterhazy16:03:22

well if it's not synchronous, it'll be slow

pesterhazy16:03:56

obviously if you spin the CPU for 100ms in the on-change fn, that'll cause weirdness as well

pesterhazy16:03:12

(not that that's likely)

justinlee16:03:44

it’ll make it be janky, but if I actually understand this issue correctly (which is dubious to be fair), then it will be correct even if you spin. my understanding is that the browser will queue the OS-level keypress events while you are out on the onchange handler

justinlee16:03:59

i guess that’s easy to test. let me check.

justinlee16:03:50

yea. it works fine. no dropped chars.

justinlee16:03:07

(defn test-component []
  (let [*value (reagent/atom "")]
    (fn []
      [:input {:value     @*value
               :on-change (fn [e]
                            (loop [n 0 t 1]
                              (if (= n 1000000)
                                t
                                (recur (inc n) (* t n))))
                            (reset! *value (-> e .-target .-value)))}])))

justinlee16:03:55

the input form updates lag badly, but it is correct with respect to what you type