Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

typesafe select onChange event using reactjs and typescript

I have figured out how to tie up an event handler on a SELECT element using an ugly cast of the event to any.

Is it possible to retrieve the value in a type-safe manner without casting to any?

import React = require('react');

interface ITestState {
    selectedValue: string;
}

export class Test extends React.Component<{}, ITestState> {

    constructor() {
        super();
        this.state = { selectedValue: "A" };
    }

    change(event: React.FormEvent) {
        console.log("Test.change");
        console.log(event.target); // in chrome => <select class="form-control" id="searchType" data-reactid=".0.0.0.0.3.1">...</select>

        // Use cast to any works but is not type safe
        var unsafeSearchTypeValue = ((event.target) as any).value;

        console.log(unsafeSearchTypeValue); // in chrome => B

        this.setState({
            selectedValue: unsafeSearchTypeValue
        });
    }

    render() {
        return (
            <div>
                <label htmlFor="searchType">Safe</label>
                <select className="form-control" id="searchType" onChange={ e => this.change(e) } value={ this.state.selectedValue }>
                    <option value="A">A</option>
                    <option value="B">B</option>
                </select>
                <h1>{this.state.selectedValue}</h1>
            </div>
        );
    }
}
like image 285
davestevens Avatar asked Oct 21 '15 09:10

davestevens


People also ask

Is it possible to make the onchange event typesafe in react?

To make it possible, the .d.ts of react would need to be modified so that the signature of the onChange of a SELECT element used a new SelectFormEvent. The new event type would expose target, which exposes value. Then the code could be typesafe.

What event types can I use with react and typescript?

You’ve used a common event type (React.ChangeEvent<HTMLInputElement>) and made a simple web app with React and TypeScript. Continue learning more interesting stuff by taking a look at the following articles: You can also check our React topic page and React Native topic page for the latest tutorials and examples.

What is the difference between onclick and handleinputchange in react?

The onClick event is actually generated by React itself: it's a synthetic event. A synthetic event is a React wrapper around the native browser event, to always have the same API regardless of differences in browsers. Let's move on to the handleInputChange function. It's pretty similar to handleClick, with a significant difference.

Is it type-safe to use event target with htmlselectelement?

The TypeScript compiler will allow this type-assertion, because an HTMLSelectElement is an EventTarget. After that, it should be type-safe, because you know that e.target is an HTMLSelectElement, because you just attached your event handler to it.


Video Answer


3 Answers

I tried using React.FormEvent<HTMLSelectElement> but it led to an error in the editor, even though there is no EventTarget visible in the code:

The property 'value' does not exist on value of type 'EventTarget'

Then I changed React.FormEvent to React.ChangeEvent and it helped:

private changeName(event: React.ChangeEvent<HTMLSelectElement>) {
    event.preventDefault();
    this.props.actions.changeName(event.target.value);
}
like image 81
Sergei Basharov Avatar answered Oct 16 '22 12:10

Sergei Basharov


Since upgrading my typings to react 0.14.43 (I'm not sure exactly when this was introduced), the React.FormEvent type is now generic and this removes the need for a cast.

import React = require('react');

interface ITestState {
    selectedValue: string;
}

export class Test extends React.Component<{}, ITestState> {

    constructor() {
        super();
        this.state = { selectedValue: "A" };
    }

    change(event: React.FormEvent<HTMLSelectElement>) {
        // No longer need to cast to any - hooray for react!
        var safeSearchTypeValue: string = event.currentTarget.value;

        console.log(safeSearchTypeValue); // in chrome => B

        this.setState({
            selectedValue: safeSearchTypeValue
        });
    }

    render() {
        return (
            <div>
                <label htmlFor="searchType">Safe</label>
                <select className="form-control" id="searchType" onChange={ e => this.change(e) } value={ this.state.selectedValue }>
                    <option value="A">A</option>
                    <option value="B">B</option>
                </select>
                <h1>{this.state.selectedValue}</h1>
            </div>
        );
    }
}
like image 41
davestevens Avatar answered Oct 16 '22 11:10

davestevens


In my case onChange event was typed as React.ChangeEvent<HTMLSelectElement>:

onChange={(e: React.ChangeEvent<HTMLSelectElement>) => {
  console.warn('onChange TextInput value: ' + e.target.value);
}}
like image 19
Jackkobec Avatar answered Oct 16 '22 12:10

Jackkobec