React-select: getting the "event" on "onChange(val, [selectedOptions])"?

Created on 14 Dec 2015  路  17Comments  路  Source: JedWatson/react-select

i want to access the event.target props onChange,
is it possible?

thanks

Most helpful comment

+1. The workaround mentioned above has performance downsides. It would be great if the event was simply passed in like this.

  onChange = (val, event) => {
    this.setState({[event.target.name]: val});
  };

All 17 comments

What are trying to achieve?

i have 3 select boxes that share one onChange function. i want to access the select box's props by using e.target.

for now i use 3 different functions for each select box cause i couldn't figure it out.

any ideas? 馃槑

I have a similar issue. I'm using this component in an Angular app, and the select is inside an ng-repeat. In the onChange callback, I need some way to know which select triggered the callback, otherwise I can't update that specific select with a new value. I'm adding a unique ID to the name attribute, so passing that at the very least as another parameter in the onChange callback would be helpful.

+1 on needing to access event object.

+1 it would be great to add that feature, so I won't need to add an onChange function for each select item. Is there a workaround for this?

+1 ! having the event as second arg would be very neat..

+1

In my case, I was trying to get the value of the name attribute (e.target.name). I've found this workaround which did the trick: https://github.com/JedWatson/react-select/issues/520#issuecomment-148471241

+1. The workaround mentioned above has performance downsides. It would be great if the event was simply passed in like this.

  onChange = (val, event) => {
    this.setState({[event.target.name]: val});
  };

+1. At least event.target.name should be passed along as a second parameter so the parent component that controls the select element can distinguish between multiple instances of select-elements and store the values under different keys in its state.

This issues seems pretty old and still nothing - this option is very useful. Trying to figure this out right now and found similar issues here.

Came up with a solution that returns an "event" parameter with the correct target element. I ended up using addEventListener and dispatchEvent to create a new Event and attach the required properties to it. The ReactSelect component didn't accept a ref property either so I had to use firstChild in the ref'ed element. Also had to stub the persist function since it's used higher up.

import React, { Component } from 'react';
import ReactSelect from 'react-select';
import PropTypes from 'prop-types';

class Dropdown extends Component {

    static propTypes = {
        onChange: PropTypes.func.isRequired,
        name: PropTypes.string.isRequired,
        multi: PropTypes.bool,
    }

    static defaultProps = {
        multi: false,
    }

    constructor (props) {
        const selected = props.multi ? [] : {};

        super(props);
        this.state = { selected };
    }

    componentDidMount () {
        const DropdownElement = this.element.firstChild;
        DropdownElement.addEventListener('change', (e) => {
            const { selected } = this.state;
            const { name, onChange } = this.props;

            event.target.name = name;
            event.persist = () => {};
            event.target.value = selected;
            onChange(e, selected);
        }, false);
    }

    setRef = (element) => (
        this.element = element
    )

    handleChange = (selected) => {
        const event = new Event('change');
        const DropdownElement = this.element.firstChild;
        this.setState({ selected }, () => (
            DropdownElement.dispatchEvent(event)
        ));
    }

    render () {
        const { selected } = this.state;
        const value = this.props.multi ? selected : selected.value;

        return (
            <div ref={this.setRef}>
                <ReactSelect {...this.props} value={value} clearable={false} onChange={this.handleChange} />
            </div>
        );
    }
}

export default Dropdown;

Seems easy enough to just pass the name attribute as an argument to the onChange function. This works just fine:

<Select onChange={(e) => this.onSelectChange(e, "total_bathrooms")}
             name="total_bathrooms"
             value={data.total_bathrooms}
             options={bathroomOptions}
             clearable={false}
             placeholder="Select property bathrooms"
/>

And then for the onSelectChange function:

onSelectChange = (e, name) => {
        this.setState({
            data: { ...this.state.data, [name]: e.value }
        })
    };

+1 Does the team provide the solution?

Here is what I came up with: https://gist.github.com/cyrilf/109fc97a22cd080abcc5068a30976696
It's not perfect and a bit hacky, but in my case I really needed to access a full event object. (constraint from an abstract code wrapping all my fields elements).
Hope it helps!

thanks! @Krucial92

My understanding is that the event is not accessible because there is not one. This is because react-select creates events for which there is no corresponding native event. This is a limitation of the spec for selects, and instead of creating fake native events they've left it up to you to do that.

I think the real underlying problem here is libraries like Formik (for example) asking for very large objects like the React synthetic event object when they only care about 2-3 fields.

See below issue for detailed discussion about why.
https://github.com/JedWatson/react-select/issues/1631

Especially these two comments
https://github.com/JedWatson/react-select/issues/1631#issuecomment-555986192
https://github.com/JedWatson/react-select/issues/1631#issuecomment-556090188

Was this page helpful?
0 / 5 - 0 ratings

Related issues

Meesam picture Meesam  路  3Comments

MalcolmDwyer picture MalcolmDwyer  路  3Comments

batusai513 picture batusai513  路  3Comments

coder-guy22296 picture coder-guy22296  路  3Comments

yrabinov picture yrabinov  路  3Comments