Recompose: Allow self-controlled component to be controlled from the outside

Created on 10 Jan 2018  路  2Comments  路  Source: acdlite/recompose

I was hoping to achieve with this library something similar to what's possible with uncontrollable: a component that self-manages its own state, say an <input type="text" {...} />, but that also allows its parent to control it, if the value (and possible the onChange) prop is given.

This is sort of possible, according to what's pointed out here, but I think that doesn't solve the issue completely, for a couple of reasons:

  1. The definitive criteria to determine if the outside of the component is trying to control it, should not be the presence or not of the state setter prop (the onChange), but rather the presence or not of the value. If the value is given as a prop from the outside, that should be the thing that triggers the component to relinquish control.
  2. That technique forces one to "make up" a couple of different names for the property setter, in order to be able to discern in the mapProps which one to pass.
  3. In the "uncontrolled mode", where the controller manages the state internally, it is often desirable to parameterize the initial value of the uncontrolled prop, i.e. defaultValue in the example.

My question is: is it possible to achieve this (at least points 1 and 2 above) using primitives from this library alone, without the caveats mentioned about the example on #7? And if not, wouldn't it make sense to add it, either improving some of the primitives, or providing a new one?

Follow up question: I'm pretty certain that the point 3 above is not achievable, because it seems a more ad-hoc thing to be done in order to sort of match that defaultX is meant to initialize state.x. Would this be something that makes sense to add to this library as well?

PS: I'm more than happy to work on a PR myself if anything of what I propose makes sense.

Most helpful comment

usually branch + withStateHandlers is enough.

branch(
// as value can be empty better to check that no handler passed
  ({ onChange }) => !onChange,
  withStateHandlers(
  ({ defaultValue }) => ({ value: defaultValue}),
   onChange: () => value => ({ value })
  )
)

All 2 comments

usually branch + withStateHandlers is enough.

branch(
// as value can be empty better to check that no handler passed
  ({ onChange }) => !onChange,
  withStateHandlers(
  ({ defaultValue }) => ({ value: defaultValue}),
   onChange: () => value => ({ value })
  )
)

Wow great! It certainly is possible with the primitives already in place. Thanks!

I'd still use it (as I am doing in my case right now) with the criteria being value === undefined, instead of using the presence of the onChange handler. I think is more precise. Otherwise, it seems unintuitive that the outside world gives my component a value and no onChange, and my component continues to control itself, when the presence of the value prop suggest otherwise.

Anyway, thanks. This library is more awesome each day I use it.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

astanciu picture astanciu  路  3Comments

adrianmcli picture adrianmcli  路  3Comments

cdomigan picture cdomigan  路  4Comments

nemocurcic picture nemocurcic  路  3Comments

robbporto picture robbporto  路  3Comments