React-redux-form: Feature Suggestion / API change - Custom Controls with `render` prop

Created on 18 Dec 2017  路  3Comments  路  Source: davidkpiano/react-redux-form

Basic Idea

Control (and Control.custom) have limited flexibility / opaque behaviours by design. Whilst we can define a component to pass props to, we have limited control over what props are passed around, or how rendering takes place downstream.

"Render props" solves this issue by deferring rendering / mapping implementation details to a consumer.

I'm proposing an API that looks like:

<Control model="some.path" render={({onChange, onFocus, value, ...etc}) => (
  <MyCustomInput label="something" onChange={onChange} {...etc} />
)}/>

With a render props API we defer rendering / mapping responsibilities to the user (a "cost") whilst increasing flexibility in how exactly the props we're providing are used (a benefit).

API Compatibility

I think we can avoid API breaking changes by only implementing "render props behaviours" in a case where a function is passed as the render prop. This _should_ prevent breaking changes for existing consumers, whilst providing this API as an opt-in for new consumers who prefer it

Other Stuff

render props are becoming more and more "idiomatic react" (alternatively "function as children" works too!) and I think this in itself is a value add.

I'm happy to take on the work of adding this if people are in to the idea. Cheers!

Most helpful comment

@davidkpiano looks to me like the Errors component could benefit from a similar API. Support all the existing props, but allow a render prop as a more flexible alternative to wrapper and component. Would be happy to do this also. Any concerns?

edit: In this case the show prop might be more appropriately named "filter" or something, and it can filter whether error messages are passed in.

API example:

<Errors
  model="some.model"
  messages={{
    required: 'Required',
    length: 'Too long',
  }}
  filter|show|when={field => field.touched}
  render={(errors, field) => (
    // Pass in both errors and field? Why not?
    <div>
      {errors.map(error => <span>{error}</span>}
    </div>
  )}
/>

All 3 comments

I am 馃挴 for this idea, would definitely simplify a lot of things.

Have at it! It shouldn't be difficult to do - all you'd have to do is pass in the fieldValue (and other things such as model) into the function, and you should be good to go.

@davidkpiano looks to me like the Errors component could benefit from a similar API. Support all the existing props, but allow a render prop as a more flexible alternative to wrapper and component. Would be happy to do this also. Any concerns?

edit: In this case the show prop might be more appropriately named "filter" or something, and it can filter whether error messages are passed in.

API example:

<Errors
  model="some.model"
  messages={{
    required: 'Required',
    length: 'Too long',
  }}
  filter|show|when={field => field.touched}
  render={(errors, field) => (
    // Pass in both errors and field? Why not?
    <div>
      {errors.map(error => <span>{error}</span>}
    </div>
  )}
/>

I'm all for render props everywhere. What I'd recommend is keeping the amount of arguments passed to these render props as small as possible - e.g., just fieldValues for <Control>, which contains everything in an object. I want to avoid positional arguments.

Was this page helpful?
0 / 5 - 0 ratings