Skip to content

Instantly share code, notes, and snippets.

@leocristofani
Last active June 8, 2020 14:59
Show Gist options
  • Save leocristofani/98312e61807db8f32e720c9f97a186e5 to your computer and use it in GitHub Desktop.
Save leocristofani/98312e61807db8f32e720c9f97a186e5 to your computer and use it in GitHub Desktop.
How to integrate React Select with Redux Form
import React, { PropTypes } from 'react';
import Select from 'react-select';
import 'react-select/dist/react-select.css';
RFReactSelect.defaultProps = {
multi: false,
className: ""
};
RFReactSelect.propTypes = {
input: PropTypes.shape({
name: PropTypes.string.isRequired,
value: PropTypes.string.isRequired,
onBlur: PropTypes.func.isRequired,
onChange: PropTypes.func.isRequired,
onFocus: PropTypes.func.isRequired,
}).isRequired,
options: PropTypes.array.isRequired,
multi: PropTypes.bool,
className: PropTypes.string
};
export default function RFReactSelect({ input , options, multi, className }) {
const { name, value, onBlur, onChange, onFocus } = input;
const transformedValue = transformValue(value, options, multi);
return (
<Select
valueKey="value"
name={name}
value={transformedValue}
multi={multi}
options={options}
onChange={multi
? multiChangeHandler(onChange)
: singleChangeHandler(onChange)
}
onBlur={() => onBlur(value)}
onFocus={onFocus}
className={className}
/>
);
}
/**
* onChange from Redux Form Field has to be called explicity.
*/
function singleChangeHandler(func) {
return function handleSingleChange(value) {
func(value ? value.value : '');
};
}
/**
* onBlur from Redux Form Field has to be called explicity.
*/
function multiChangeHandler(func) {
return function handleMultiHandler(values) {
func(values.map(value => value.value));
};
}
/**
* For single select, Redux Form keeps the value as a string, while React Select
* wants the value in the form { value: "grape", label: "Grape" }
*
* * For multi select, Redux Form keeps the value as array of strings, while React Select
* wants the array of values in the form [{ value: "grape", label: "Grape" }]
*/
function transformValue(value, options, multi) {
if (multi && typeof value === 'string') return [];
const filteredOptions = options.filter(option => {
return multi
? value.indexOf(option.value) !== -1
: option.value === value;
});
return multi ? filteredOptions : filteredOptions[0];
}
@Misiur
Copy link

Misiur commented Aug 22, 2017

https://github.com/erikras/redux-form/blob/ca00a778af5e2ca5079fc9cac153bd33dd1e313d/src/ConnectedField.js#L106-L110 I have some problems because of this piece of code.
image
Because onChange doesn't receive event object but just a plain value, my custom onChange receives this weird construct. I can bypass it by setting a new onCustomChange callback which is called by your handleSingleValue, but if anybody has a better idea, I'd appreciate it.

@ramoncaldeira
Copy link

I was able to run Creatable successfully by decorating the options parameter before the render function of my custom input component Field.

let values = input.value.split(',');
values.map(value => {
  if(Boolean(value) && !_find(options, {value})) {
   options.push({label: value, value});
  }
});

@addicted2sounds
Copy link

thanks :) you saved my day 👍

@dinshaw
Copy link

dinshaw commented Aug 16, 2018

Thank you for sharing the amazing work. After reading every post out there on react-select/redux-form, this is the only one that works for me. I'm trying to get a default value set, but I'm unsure where to put it. The pattern seems to be to have 'value' come from the component's state, and update that state onChange. I've been playing around with changing export default function RFReactSelect to a full React.Component so I can give it state, but haven't been able to get it right. Any suggestions?
Thank you!

@mciszczon
Copy link

I'm using react 15.4.1, redux-form 7.0.1 and react-select 2.0.0. I've used your code and still got the same problem: values were cleaned from store after the blur event.

Found out, that the onBlur={() => onBlur(value)} override was not needed. After I had removed this line, it started working well! Thanks for the handy snippet!

@gurmeetsinghmalhotra
Copy link

gurmeetsinghmalhotra commented Jun 8, 2020

With the introduction of "actionMeta". How can we incorporate it in "multiChangeHandler" to get the meta information like "name" of the field in our custom onchangehandler?

Currently this is how we have to make it run

handleChangeCreatable = (newValue, actionMeta, prevValue, name) => {
        this.setState({
            [name]: newValue
        });
    };

@leocristofani
Copy link
Author

@gurmeetsinghmalhotra thanks for your comment, but I no longer maintain this gist since I moved away from using Redux and Redux Form long ago. Best of luck!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment