Search code examples
reactjsredux-form

Wrapping UI components to use with Redux Form, and use custom onChange event functions


The following is a custom dropdown menu that I would like to make compatible with Redux Form, as well as execute custom onChange function (e.g.: dispatch an action)

<Select
  label='Team'
  name='team'
  options={teamOptions}
  placeholder='Team'
  onClick={this.handleTeamClick}
/>

In a first step, I created the wrapper as follows:

export const rfSelect = ({ input, options, meta, ...rest }) => (
  <Select {...input} onChange={(e,v) => input.onChange(v.value)} options={options} {...rest} />
)

where the default onChange() of the Select component is called.

The wrapper component is used with Redux Form like this:

<Field
  component={rfSelect}
  label='Team'
  name='team'
  options={teamOptions}
  placeholder='Team'
  onClick={this.handleTeamClick}
/>

So far, everything is good. The UI element displays the new selected value when a new value is chosen from the dropdown.

In step 2, I would like to pass a custom onChange event. This is what it looks like:

<Field
  component={rfSelect}
  label='Team'
  name='team'
  options={teamOptions}
  placeholder='Team'
  onClick={this.handleTeamClick}
  onChange={this.handleTeamChange}
/>

handleTeamChange(e, sel) {
  this.props.dispatch(bla.handleTeamChange(sel.value))
}

export const rfSelect = ({ input, options, meta, ...rest }) => (
  <Select {...input} onChange={(e,v) => input.onChange(v.value)} options={options} {...rest} />
)

Here, the default onChange was replaced by the custom one that I passed in. handleTeamChange is called correctly and the action is dispatched.

However, passing my own onChange now no longer updates the selected value upon choosing from the dropdown. In other words, i select a dropdown item but the value remains blank.

Bottomline: I am either able to have the UI component update the selected value correctly, or execute my custom onChange event. But not both.

Here are the ideas that I could think of in order to solve this problem:

  • in the custom onChange function, handle the update of the selected value manually
  • pass in the custom onChange function as onChange2 instead of onChange (meaning it will not overload the default function), and then let the component wrapper call both input.onChange(...) and onChange2(...).

Though both these alternatives are quite hacky, and I am not particularly fond of either. I have not yet been able to code them successfully either, so they are just ideas so far.

For the first option, printing e in the handleTeamChange function above shows the following, which i have tried (and failed) to use to manually set the Select component's value:

enter image description here

Any input on this would be greatly appreciated.

Thanks!


Solution

  • Allowing custom onChange handlers to be given to Field is a feature I'm considering for a future version of the library.

    You are on the right track with your hack ideas. Something like this should work:

    export const rfSelect = ({ input, meta, onChange, ...rest }) => (
      <Select {...input} onChange={(e,v) => {
        input.onChange(v.value) // update redux-form value
        onChange(v.value)       // call your additional listener
      }} {...rest} />
    )
    

    I removed options, because it's there in ...rest, and you can even call your prop onChange as it's separate from the one in input.

    Hope this helps.