React-select: Getting value onBlur

Created on 13 May 2015  路  5Comments  路  Source: JedWatson/react-select

Is it possible to get the value of select on blur? Unlike onChange onBlur returns an event. So when I do something like e.target.value I always get an empty string.

Most helpful comment

+1

All 5 comments

@anthonator I'm not familiar, but with a typical onBlur event for a text box, is the e.target.value the text from the text box? We should probably mimic typical components in this respect.

Yes, e.target.value is the value of the input.

:+1: for adding this.

would be nice if the first argument passed to the onChange callback was a similar event rather than just the value.

P.S This issue was killing me today in conjunction with #188, as I want to trigger validation after the initial blur event, then on subsequent change events.

If anyone else is in a similar situation, I ended up resolving it with this wrapper component.
The faux event objects are naive, but I only need e.type and e.target.value

'use strict';

var React = require('react');
var Select = require('react-select');

module.exports = React.createClass({

    displayName: 'SelectWrapper',

    getDefaultProps () {
        return {
            value: null
        }
    },

    getInitialState () {
        return {
            value: this.props.value
        }
    },

    onBlur () {
        let blurHandler = this.props.onBlur;
        if (blurHandler) {
            blurHandler({
                type: 'blur',
                target: {
                    value: this.state.value
                }
            })
        }
    },

    onChange (value) {

        let changeHandler = this.props.onChange;
        if (changeHandler) {
            changeHandler({
                type: 'change',
                target: {
                    value: value
                }
            });
        }

        this.setState({ value: value });
    },

    render () {
        let { onBlur, onChange, value, ...props } = this.props;

        return (
            <Select onBlur={ this.onBlur } onChange={ this.onChange } { ...props } { ...this.state } />
        );
    }

});

+1

馃憤 for adding this.

would be nice if the first argument passed to the onChange callback was a similar event rather than just the value.

P.S This issue was killing me today in conjunction with #188, as I want to trigger validation after the initial blur event, then on subsequent change events.

If anyone else is in a similar situation, I ended up resolving it with this wrapper component.
The faux event objects are naive, but I only need e.type and e.target.value

'use strict';

var React = require('react');
var Select = require('react-select');

module.exports = React.createClass({

    displayName: 'SelectWrapper',

    getDefaultProps () {
        return {
            value: null
        }
    },

    getInitialState () {
        return {
            value: this.props.value
        }
    },

    onBlur () {
        let blurHandler = this.props.onBlur;
        if (blurHandler) {
            blurHandler({
                type: 'blur',
                target: {
                    value: this.state.value
                }
            })
        }
    },

    onChange (value) {

        let changeHandler = this.props.onChange;
        if (changeHandler) {
            changeHandler({
                type: 'change',
                target: {
                    value: value
                }
            });
        }

        this.setState({ value: value });
    },

    render () {
        let { onBlur, onChange, value, ...props } = this.props;

        return (
            <Select onBlur={ this.onBlur } onChange={ this.onChange } { ...props } { ...this.state } />
        );
    }

});

You might want to slightly change this.
OnBlur can trigger very quickly after onChange. setState is async call. So if you are calling changeHandler and then setState, there's a good chance that you might have not received the value you have set in state for onBlur event.
Try this scenario

  1. Select the option
  2. OnChange triggers and ChangeHandler() is called (state value is null)
  3. The selected value is returned through your ChangeHandler() but state value is still null.
  4. Setstate is called to assign the selected option to state (no guarantee on state value to be set immediately since it is asynchronous)
  5. OnBlur is triggered immediately (if you are not using 'blurInputOnSelect' prop to keep the focus still)
  6. At this point state value might have not been set yet (state value still could be null)

But here you were expecting the state value which was set by OnChange

So you could first call setState and use the callback to trigger OnChangeHandler

onChange = (e) => {
        const { value } = e
        let changeHandler = this.props.clickHandler;
        this.setState({ value: value }, () => {
            if (changeHandler) {
                changeHandler({
                    value: value,
                    name: this.props.name
                });
            }
        });
    }
    onBlur = () => {
        const { value } = this.state;
        let blurHandler = this.props.blurHandler;
        if (blurHandler) {
            blurHandler({
                value: value,
                name: this.props.name,
            })
        }
    }
Was this page helpful?
0 / 5 - 0 ratings