Fork me on GitHub
#reagent
<
2021-10-01
>
Ben Halton09:10:04

I'm using reagent in conjunction with MUI5. There is a well known issue with the cursor jumping to the end of the input when trying to edit in the middle of a text field. I've sorted that by following: https://github.com/reagent-project/reagent/blob/master/doc/examples/material-ui.md. This works for text fields but if I use :type "number"the jumping happens again.

Ben Halton09:10:21

I also see the following error

Ben Halton09:10:38

MUI: You have provided a `inputComponent` to the input component
that does not correctly handle the `ref` prop.
Make sure the `ref` prop is called with a HTMLInputElement. 

Ben Halton09:10:28

I also see some other slightly annoying things, like label shrink behaviour not working very well, although I think I can work around this

Ben Halton09:10:10

I'd really like to switch to controlled inputs in my app but I'm really struggling to get this behaviour 100%

p-himik10:10:16

That Reagent examples uses v4 while you're using v5, so that's where all the issues come from. One possible solution is to wrap the uncontrolled MUI input in a controlled component and have the external value supplied to MUI input be specified only when it truly changes externally and not via the MUI input itself. re-com adheres to this model: https://github.com/day8/re-com/blob/07451b1d19c59eb185548efe93e2d00b5d3eab89/src/re_com/input_text.cljs#L97-L99

Ben Halton10:10:09

thanks yeah I figured v5 might be the issue. I'll take a look at the example thanks. I feel like the issue with number inputs might have also affected us with v4 MUI but rolling back just now is a bit painful

p-himik10:10:52

If you're really curious and just want to test the number input on v4, you can just create a small test project - no need to roll back anything. But also, if you're using Git, rolling back while preserving all the changes in a separate branch is just a couple of commands. :)

Ben Halton10:10:10

yes - not so much the version of code that concerns me - I'm not very clued up with node/npm/shadow

Ben Halton10:10:36

so i'm concerned about dependency hell !

p-himik10:10:07

That's not really a concern - you just remove node_modules and run npm i again, that's it.

Ben Halton10:10:39

:thumbsup::skin-tone-2:

Ben Halton11:10:51

so I went back to have a look at v4 - it seemed to work well with numbers, and no console warning. I'd say with v5, using the old approach, text fields still work (but with console error) and number inputs are a bit odd - occasional jumping

Ben Halton11:10:29

at the risk of being thick - is there a way to make the inputComponent satisfy the warning ?

Ben Halton11:10:00

i.e. be an instance of HTMLInputElement?

Ben Halton11:10:40

I think short term I can make this kinda work by using text inputs and enforcing the number type another way - but obviously the error worries me a bit

p-himik11:10:01

No clue, I haven't switched from Material UI v4 myself.

Ben Halton11:10:42

sensible 🙂 I need to dig into reagent a little I think

Ben Halton13:10:58

well I spent a little time looking at this and didn't get far. This example

(def ^:private input-component
  (r/reactify-component
    (fn [props]
      [:input (-> props
                  (assoc :ref (:inputRef props))
                  (dissoc :inputRef))])))
doesn't seem valid now as props no longer seems to contain an :inputRef and tbh I'm not really sure what should go there

p-himik13:10:44

Have you tried the internal/external model approach yet?

Ben Halton14:10:08

not yet no - have been fiddling back and forth with v4 / v5 trying to spot the difference

Ben Halton14:10:35

will try to get a proper look over the weekend

p-himik14:10:59

I don't think that approach is worth the time - the differences can easily include implementation details and most likely include some API you will never use elsewhere. Whereas the internal/external model approach will work with any component, from any library. It's well worth learning it by itself.

Ben Halton14:10:05

yes I think I'm facing up to reality fairly quickly 🙂 I thought there might be magic incantation

Ben Halton07:10:46

so I had a look through the code and tried a few things myself - I could just be being thick but I don't see how that provides a fix for rerendering uncontrolled mui components? the problem with those is that re-rendering the component doesn't change the default-value, The only way I've found to force the re-render is to force a change in the key value of the component, this works but it feels a bit unwieldy.

p-himik07:10:53

Hold on. Your initial problem was caused by unneeded re-rendering. But now you actually do want to re-render? What gives?

Ben Halton07:10:43

I want to be able to control the value in the input externally

Ben Halton07:10:29

if I do this with a standard controlled input - I get cursor jumping

Ben Halton07:10:53

if I do it with a uncontrolled input - I don't get cursor jumping, but am unable to control the value in the input

Ben Halton07:10:00

unless I'm missing something fundamental ?

Ben Halton07:10:39

which is definitely possible - I"m really not much of a UI dev

p-himik07:10:13

Ah, right. The :key trick is an alright solution - I'd probably use it myself as well.

Ben Halton07:10:07

I nunderstood the old workaround of supplying a reagent input component to the MUI textfield - this meant reagent could apply cursor fixing

Ben Halton07:10:45

obviously I'd like to repeat that here but looking at the docs, its a bit beyond my react/js/reagent comprehension (if it's possible at all)

Ben Halton07:10:18

the section on integration with 3rd party input libs seems to be what we want

Ben Halton07:10:13

but how we supply a custom reagent managed input component that implements the right interface is a bit much for me

p-himik07:10:32

If :key works, why would you want to use something else?

Ben Halton07:10:38

anyway appreciate the help :thumbsup::skin-tone-2:

Ben Halton07:10:13

it seems more elegant to me - to use inbuilt fixes for a known issue - both react and reagent have their own fixes for cursor jumping

Ben Halton07:10:53

instead I need to implement a custom fix - I have done this elsewhere already but preferred the elegance of supplying a managed input

p-himik07:10:08

It's only elegant on the surface. :key + internal/external model will work for any kind of input, from any library. Whereas that solution of providing a custom component works only for that particular version of MUI, and nothing else.

Ben Halton07:10:18

that's a fair point

Ben Halton07:10:26

I have some abstractions I've built for forms and I guess I'll need to rework them to include a generic way to do "controlled" components at the momen the way I handle them is a bit ad hoc

p-himik08:10:28

Belatedly realized that I somewhat led you astray with that re-com link since re-com wraps controlled components. And an uncontrolled component needs a tad different approach. Sorry about that. But seems like you have figured that out already.

p-himik08:10:51

Just dug out some old code and found that I used (reagent.core/flush) in the :on-change handler there. I think it basically turns async rendering into a sync one, thus fixing the initial problem.

Ben Halton08:10:41

ah yes thanks - this is the path I was just heading down

Ben Halton08:10:34

was just seeing that react itself possibly does some sync update magic to work around the issue

Ben Halton08:10:00

I'm also looking at options of managing cursor position myself - this has some potential

Ben Halton09:10:52

I think I have come up with something based on managing cursor position myself ... seems to work at first glance so I'll get on and test this afternoon

Benjamin16:10:28

I'm looking for some apps "made with clojurescript" (krell, reagent whatever). Reason is so my team mates can see for themselves if they can be made with quick startup / zappy