Skip to content

Instantly share code, notes, and snippets.

@cyrilf
Created August 30, 2018 15:45
Show Gist options
  • Star 8 You must be signed in to star a gist
  • Fork 4 You must be signed in to fork a gist
  • Save cyrilf/109fc97a22cd080abcc5068a30976696 to your computer and use it in GitHub Desktop.
Save cyrilf/109fc97a22cd080abcc5068a30976696 to your computer and use it in GitHub Desktop.
Solution to receive an event with react-select onChange method
// Issue: `react-select` `onChange` method doesn't return a proper event
//
// Solution used:
//
// The main idea is to have an hidden `select` that will trigger a real event
// When `ReactSelect` triggers it's `onChange` we set the state with the `selectedOptions`
// these `selectedOptions` will be what populate our hidden select.
// Using the callback from `setState` (it ensures that the new values are already into our hidden select),
// we then create a change event and dispatch it into our hidden select.
// This will cause the `onChange` from this select to be triggered with a proper `event`.
// :tada:
import React from "react"
import ReactSelect from "react-select"
class MultipleSelect extends React.Component {
constructor(props) {
super(props)
this.hiddenSelect = React.createRef()
}
state = {
selectedOptions: this.props.options.filter(option => option.selected),
}
// the react-select only gives us an array of selected option
// so we generate a "fake" change event on our 'native' select
handleChange = (selectedOptions) => {
this.setState(() => ({ selectedOptions }), () => {
// ! this is a bit hacky.. use at your own risk ;) !
const event = new Event("change", { bubbles: true })
this.hiddenSelect.current.dispatchEvent(event)
})
}
handleNativeChange = (event) => {
// you can do whatever with the event here.
// event.target.options is a good one :wink:
// in my case I give it back to `this.props.onChange(event)`
}
render() {
const { title, name, options } = this.props
const { selectedOptions } = this.state
return (
<div>
<ReactSelect
value={selectedOptions}
onChange={this.handleChange}
options={options}
isMulti
closeMenuOnSelect={false}
/>
<select
multiple
ref={this.hiddenSelect}
name={name}
onChange={this.handleNativeChange}
value={selectedOptions.map(option => option.value)}
readOnly
className="d-none">
{selectedOptions.map(option => <option key={option.label} value={option.value}>{option.label}</option>)}
</select>
</div>
)
}
}
export default MultipleSelect
@osmanperviz
Copy link

Thank you man, you save my day 👍 Hope you are good :)

@fsartoris
Copy link

Thanks for the tip! After 2 years there is still be a great approach!

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