React-select: Need example on integration with redux form

Created on 31 Jul 2016  路  19Comments  路  Source: JedWatson/react-select

  • Hi, I'm quite new to react and redux. Tried integrating react-select with redux form but struggling to assign selected value to the field. It would be grateful of you if you can provide an example implementing the same. Thank you.

Most helpful comment

For me, the following works for [email protected] and [email protected]

<Select
  value={input.value}
  onChange={input.onChange}
  onBlur={() => input.onBlur(input.value)}
  options={optionsToRender}
  placeholder={placeholder}
  className="form-control"
  simpleValue
/>

All 19 comments

export class ReactSelectWrapper extends React.Component {

  constructor(props) {
    super(props);
  }

  render = () => {

    return (<Select
      {...this.props}
    />);
  }

}

export const renderReactSelectWrapper = props => (<ReactSelectWrapper {...props}/>);


var options = [
      { value: 'one', label: 'One' },
      { value: 'two', label: 'Two' }
    ];

<Field name="name" component={renderReactSelectWrapper} options={options}>


There is a major problem, the selected value gets cleared on blur. This can't be prevented by onBlurResetsInput(false). If anyone has any suggestion to avoid this, you're welcome to provide any help.

You're probably not setting the value prop in your react-select component. So when Redux updates state, it blows away any selection made.

Your code sample is missing an onChange handler (not sure if you excluded that on purpose). That onChange handler should call a Redux action to set state to the selected value. Then use that value to set react-select's value prop.

That should do the trick. :)

@gojohnnygo The onChange should be wired up via the spread operator {...props} in @duketwo sample code.

I was also having this problem and when I was trying to debug it I changed my code like this

const MemberSelect = ({users, onChange, value, onBlur}) => {
  const usersOptions = users.map(
    user => ({
      label: user.firstName + " " + user.lastName,
      value: user.id
    }));

  function handleChagne(value) {
    onChange(value);
  }

  function handleBlur() {
    onBlur();
  }

  // https://github.com/JedWatson/react-select/issues/1129
  return (
    <FormElement name="members" label="Members">
      <Select
        name="members"
        options={usersOptions}
        multi
        simpleValue
        disabled={false}
        onChange={handleChagne}
        value={value}
        onBlur={handleBlur}
        onBlurResetsInput={false}/>
    </FormElement>
  );
};

Having the code like this with handleBlur calling onBlur from Redux Forms works for some reason while the code below that directly wires Redux Forms' onBlur doesn't work.

import React, {PropTypes} from "react";
import FormElement from "../../common/forms/FormElement";
import Select from "react-select";

const MemberSelect = ({users, onChange, value, onBlur}) => {
  const usersOptions = users.map(
    user => ({
      label: user.firstName + " " + user.lastName,
      value: user.id
    }));

  function handleChagne(value) {
    onChange(value);
  }

  // https://github.com/JedWatson/react-select/issues/1129
  return (
    <FormElement name="members" label="Members">
      <Select
        name="members"
        options={usersOptions}
        multi
        simpleValue
        disabled={false}
        onChange={handleChagne}
        value={value}
        onBlur={onBlur}
        onBlurResetsInput={false}/>
    </FormElement>
  );
};

MemberSelect.propTypes = {
  users: PropTypes.array.isRequired,
  onChange: PropTypes.func.isRequired,
  members: PropTypes.array
};

export default MemberSelect;

On further testing it looks like the proxy that is being pass to onBlur might be causing problems for Redux Forms. The code below causes things to stop working for me.

  function handleBlur(proxy) {
    onBlur();
  }

  return (
    <FormElement name="members" label="Members">
      <Select
        name="members"
        options={usersOptions}
        multi
        simpleValue
        disabled={false}
        onChange={onChange}
        value={value}
        onBlur={handleBlur}/>
    </FormElement>
  );

so it seems like it's having that proxy passed along that's causing the problem.

Looks like Redux Form is expecting a synthetic event or the current value. In chrome it looks like a synthetic event coming through so not sure what the problem is.

image

onBlur(eventOrValue) : Function

A function to call when the form field loses focus. It expects to either receive the React SyntheticEvent or the current value of the field.

https://github.com/erikras/redux-form/blob/922f320db94f8a649edbe4fcc2997ca636f750ec/docs/api/Props.md

I don't know if it's a regression, or just change of behavior but I am noticing the onChange in react-select is receiving the { label, value } object, and redux-form expects onChange to receive value so I did this:

const selInput = (props) => {
  const { children, input, options } = props
  function handleInputChange({ value }) {
    props.input.onChange(value)
  }
  return (
    <label className={props.className}>
      {children}
      <Select
        clearable={false}
        searchable={false}
        options={options}
        {...input}
        onChange={handleInputChange}
      />
    </label>
  )
}

<Field name="browser" className="browser-dropdown" component={selInput} options={browsers}>
    Browser used
</Field>

This didn't seem to be the case pre-rc4

Closing this issue since it seems to have been answered sufficiently already. :smile:

Also, this sort of question is probably better suited to Stack Overflow (or similar) rather than GitHub since it's a request for help and not a bug/feature. :grin:

For me, the following works for [email protected] and [email protected]

<Select
  value={input.value}
  onChange={input.onChange}
  onBlur={() => input.onBlur(input.value)}
  options={optionsToRender}
  placeholder={placeholder}
  className="form-control"
  simpleValue
/>

Thanks @paothegit This works very well!

@paothegit thank you, works well. Here is my Field element.

Somewhere

let options = [{value:1, label: 'select option'}];

And in render

<Field name="name" 
    component={props =>
        <Select
          value={props.input.value}
          onChange={props.input.onChange}
          onBlur={() => props.input.onBlur(props.input.value)}
          options={options}
          placeholder="Select" 
          simpleValue
        />
    } 
/>

@paothegit @kandaraj it doesn't work with multi-select because of onChange.
I answered how correct to use multi-select react-select in 82 issue.

Here is a component I created to integrate React Select with Redux Form.

This is how you can use it, and it works with both single and multi select.

const fruits = [
  { value: 'apples', label: 'Apples' },
  { value: 'bananas', label: 'Bananas' },
  { value: 'grapes', label: 'Grapes' }
];
<Field
  multi={true}
  name="fruits"
  options={fruits}
  component={RFReactSelect} />

Here is an example .... which i implemented for my form:

export class SingleSelect extends Component {
  static propTypes = {
    name: PropTypes.string,
    input: PropTypes.object,
    options: PropTypes.array,
    handleChange: PropTypes.func,
    controlLabel: PropTypes.string,
    selectedValue: PropTypes.string
  }

  onSelectChange = value => {
    let { handleChange } = this.props
    handleChange(value)
  }

  render () {
    const { options, selectedValue, controlLabel } = this.props
    return (
      <FormGroup>
        <Col md={2} lg={2} mdOffset={1} lgOffset={1}>
          <ControlLabel className={'required'} style={{lineHeight: '38px'}}>
            {' ' + controlLabel}
          </ControlLabel>
        </Col>
        <Col md={2} lg={3}>
          <Select
            options={options}
            value={selectedValue}
            onChange={this.onSelectChange}
          />
        </Col>
      </FormGroup>
    )
  }
}

And here is how you can use it in your form

<Row>
      <Field
            component={SingleSelect}
            name={'filterValueSource'}
            selectedValue={filter.filterValueSource || ''}
            controlLabel={'Filter type'}
            options={filterValueSources}
            handleChange={this.handleFilterValueSourceSelection}
      />
</Row>

I do not understand why is this issue closed.
It doesn't look like a request for help but rather some gap in the API, as onBlur does not get a regular SyntheticEvent.
Am I wrong?
Of course, the solutions mentioned above do work, thank you.

The takeaway for me on this thread is that onBlur={() => input.onBlur(input.value)} is required. As soon as I added that I was able to see my values on my redux form submit callback.

Just wanted to post here for posterity - we used the onBlur={() => input.onBlur(input.value)} solution, and after upgrading to react-select v2 my coworker had a hell of a time trying to figure out why the form state was being reset to nil specifically on Windows machines. Removing that line resolved the issue.

Just wanted to post here for posterity - we used the onBlur={() => input.onBlur(input.value)} solution, and after upgrading to react-select v2 my coworker had a hell of a time trying to figure out why the form state was being reset to nil specifically on Windows machines. Removing that line resolved the issue.

@oowowaee Can you tell me why it is especially a problem on windows machines ? We had some weired issues. Did you know which version ?

A bit late to the mix, but I added a small variation to allow redux-form to receive only the value of selected item, instead of both value and label.

In render function :

  const formattedOptions = {};
  props.options.forEach((obj) => {
    formattedOptions[obj.value] = obj;
  });
<Select
        isClearable
        value={formattedOptions[props.input.value]}
        onChange={(value) => {
          value ?
            props.input.onChange(value.value) :
            props.input.onChange(null)
        }}
        onBlur={() => props.input.onBlur(props.input.value)}
        onFocues={() => props.input.onFocus(props.input.value)}
        options={props.options}
        {...props}
      />

@kapalex You saved my bacon! 馃

I did have to make one change because it wasn't handling the case when initial values is null.

<Select
        isClearable
-       value={formattedOptions[props.input.value]}
+       value={input.value ? formattedOptions[input.value] : null}
        onChange={(value) => {
          value ?
            props.input.onChange(value.value) :
            props.input.onChange(null)
        }}
        onBlur={() => props.input.onBlur(props.input.value)}
        onFocuses={() => props.input.onFocus(props.input.value)}
        options={props.options}
        {...props}
      />

I'm using redux-form: 8.2.0 and react-select: 2.4.3.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

AchinthaReemal picture AchinthaReemal  路  3Comments

juliensnz picture juliensnz  路  3Comments

pashap picture pashap  路  3Comments

mbonaci picture mbonaci  路  3Comments

MindRave picture MindRave  路  3Comments