How to use refs in React with Typescript

前端 未结 15 1290
闹比i
闹比i 2020-11-28 05:03

I\'m using Typescript with React. I\'m having trouble understanding how to use refs so as to get static typing and intellisense with respect to the react nodes referenced by

相关标签:
15条回答
  • 2020-11-28 05:13

    Since React 16.3 the way to add refs is to use React.createRef as Jeff Bowen pointed in his answer. However you can take advantage of Typescript to better type your ref.

    In your example you're using ref on input element. So they way I would do it is:

    class SomeComponent extends React.Component<IProps, IState> {
        private inputRef: React.RefObject<HTMLInputElement>;
        constructor() {
            ...
            this.inputRef = React.createRef();
        }
    
        ...
    
        render() {
            <input type="text" ref={this.inputRef} />;
        }
    }
    

    By doing this when you want to make use of that ref you have access to all input methods:

    someMethod() {
        this.inputRef.current.focus(); // 'current' is input node, autocompletion, yay!
    }
    

    You can use it on custom components as well:

    private componentRef: React.RefObject<React.Component<IProps>>;
    

    and then have, for example, access to props :

    this.componentRef.current.props; // 'props' satisfy IProps interface
    
    0 讨论(0)
  • 2020-11-28 05:14

    To use the callback style (https://facebook.github.io/react/docs/refs-and-the-dom.html) as recommended on React's documentation you can add a definition for a property on the class:

    export class Foo extends React.Component<{}, {}> {
    // You don't need to use 'references' as the name
    references: {
        // If you are using other components be more specific than HTMLInputElement
        myRef: HTMLInputElement;
    } = {
        myRef: null
    }
    ...
     myFunction() {
        // Use like this
        this.references.myRef.focus();
    }
    ...
    render() {
        return(<input ref={(i: any) => { this.references.myRef = i; }}/>)
    }
    
    0 讨论(0)
  • 2020-11-28 05:14

    Lacking a complete example, here is my little test script for getting user input when working with React and TypeScript. Based partially on the other comments and this link https://medium.com/@basarat/strongly-typed-refs-for-react-typescript-9a07419f807#.cdrghertm

    /// <reference path="typings/react/react-global.d.ts" />
    
    // Init our code using jquery on document ready
    $(function () {
        ReactDOM.render(<ServerTime />, document.getElementById("reactTest"));
    });
    
    interface IServerTimeProps {
    }
    
    interface IServerTimeState {
        time: string;
    }
    
    interface IServerTimeInputs {
        userFormat?: HTMLInputElement;
    }
    
    class ServerTime extends React.Component<IServerTimeProps, IServerTimeState> {
        inputs: IServerTimeInputs = {};
    
        constructor() {
            super();
            this.state = { time: "unknown" }
        }
    
        render() {
            return (
                <div>
                    <div>Server time: { this.state.time }</div>
                    <input type="text" ref={ a => this.inputs.userFormat = a } defaultValue="s" ></input>
                    <button onClick={ this._buttonClick.bind(this) }>GetTime</button>
                </div>
            );
        }
    
        // Update state with value from server
        _buttonClick(): void {
        alert(`Format:${this.inputs.userFormat.value}`);
    
            // This part requires a listening web server to work, but alert shows the user input
        jQuery.ajax({
            method: "POST",
            data: { format: this.inputs.userFormat.value },
            url: "/Home/ServerTime",
            success: (result) => {
                this.setState({ time : result });
            }
        });
    }
    

    }

    0 讨论(0)
  • 2020-11-28 05:15

    EDIT: This is no longer the right way to use refs with Typescript. Look at Jeff Bowen's answer and upvote it to increase its visibility.

    Found the answer to the problem. Use refs as below inside the class.

    refs: {
        [key: string]: (Element);
        stepInput: (HTMLInputElement);
    }
    

    Thanks @basarat for pointing in the right direction.

    0 讨论(0)
  • 2020-11-28 05:16

    One way (which I've been doing) is to setup manually :

    refs: {
        [string: string]: any;
        stepInput:any;
    }
    

    then you can even wrap this up in a nicer getter function (e.g. here):

    stepInput = (): HTMLInputElement => ReactDOM.findDOMNode(this.refs.stepInput);
    
    0 讨论(0)
  • 2020-11-28 05:17

    From React type definition

        type ReactInstance = Component<any, any> | Element;
    ....
        refs: {
                [key: string]: ReactInstance
        };
    

    So you can access you refs element as follow

    stepInput = () => ReactDOM.findDOMNode(this.refs['stepInput']);
    

    without redefinition of refs index.

    As @manakor mentioned you can get error like

    Property 'stepInput' does not exist on type '{ [key: string]: Component | Element; }

    if you redefine refs(depends on IDE and ts version you use)

    0 讨论(0)
提交回复
热议问题