web-dev-qa-db-ja.com

TypescriptでReactのrefを使用する方法

ReactでTypeScriptを使用しています。 refが参照する反応ノードに関して静的型付けとインテリセンスを取得するために、refの使用方法を理解するのに問題があります。私のコードは次のとおりです。

import * as React from 'react';

interface AppState {
    count: number;
}

interface AppProps {
    steps: number;
}

interface AppRefs {
    stepInput: HTMLInputElement;
}

export default class TestApp extends React.Component<AppProps, AppState> {

constructor(props: AppProps) {
    super(props);
    this.state = {
        count: 0
    };
}

incrementCounter() {
    this.setState({count: this.state.count + 1});
}

render() {
    return (
        <div>
            <h1>Hello World</h1>
            <input type="text" ref="stepInput" />
            <button onClick={() => this.incrementCounter()}>Increment</button>
            Count : {this.state.count}
        </div>
    );
}}
78
Akshar Patel

React 16.3+を使用している場合、参照を作成するための 推奨方法React.createRef()を使用しています。

class TestApp extends React.Component<AppProps, AppState> {
    private stepInput: React.RefObject<HTMLInputElement>;
    constructor(props) {
        super(props);
        this.stepInput = React.createRef();
    }
    render() {
        return <input type="text" ref={this.stepInput} />;
    }
}

コンポーネントがマウントされると、ref属性のcurrentプロパティが参照されるコンポーネント/ DOM要素に割り当てられ、アンマウント時にnullに割り当てられます。したがって、たとえば、this.stepInput.currentを使用してアクセスできます。

RefObjectの詳細については、 @ apieceofbartの答え または PR が追加されたcreateRef()を参照してください。


以前のバージョンのReact(<16.3)を使用している場合、または参照の設定と設定解除をより詳細に制御する必要がある場合は、 “ callback refs” を使用できます。

class TestApp extends React.Component<AppProps, AppState> {
    private stepInput: HTMLInputElement;
    constructor(props) {
        super(props);
        this.stepInput = null;
        this.setStepInputRef = element => {
            this.stepInput = element;
        };
    }
    render() {
        return <input type="text" ref={this.setStepInputRef} />
    }
}

コンポーネントがマウントされると、ReactはDOM要素でrefコールバックを呼び出し、アンマウントするときにnullでそれを呼び出します。したがって、たとえば、this.stepInputを使用して簡単にアクセスできます。

refコールバックをインライン関数ではなくクラスのバインドされたメソッドとして定義することにより(この回答の 前のバージョン のように)、コールバックを回避できます 中に2回呼び出される アップデート。


そこには 以前は APIで、ref属性が文字列でした( Akshar Patelの回答 を参照)が、 someissues 、文字列参照は強く推奨されておらず、最終的には削除されます。


2018年5月22日に編集され、React 16.3でrefを実行する新しい方法が追加されました。新しい方法があったことを指摘してくれて、@ apieceofbartに感謝します。

116
Jeff Bowen

1つの方法( 私はやっています )は手動でセットアップすることです:

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

次に、これをより良いゲッター関数でラップすることもできます(例 here ):

stepInput = (): HTMLInputElement => ReactDOM.findDOMNode(this.refs.stepInput);
26
basarat

編集:これはTypeScriptでrefを使用する正しい方法ではなくなりました。JeffBowenの答えを見て、それを支持して可視性を高めます。

問題に対する答えを見つけました。クラス内で次のようにrefを使用します。

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

正しい方向を指してくれてありがとう@basarat.

17
Akshar Patel

React 16.3以降、refを追加する方法は React.createRef を使用することです。JeffBowenが答えで指摘したとおりです。ただし、TypeScriptを利用して、refをより適切に入力できます。

この例では、入力要素でrefを使用しています。だから彼らは私がそれをするだろう方法です:

class SomeComponent extends React.Component<IProps, IState> {
    private inputRef: React.RefObject<HTMLInputElement>;
    constructor() {
        ...
        this.inputRef = React.createRef();
    }

    ...

    render() {
        <input type="text" ref={this.inputRef} />;
    }
}

そのrefを使用したいときにこれを行うと、すべての入力メソッドにアクセスできます。

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

カスタムコンポーネントでも使用できます。

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

そして、例えば、小道具にアクセスできます:

this.componentRef.current.props; // 'props' satisfy IProps interface
14
apieceofbart

Reactのドキュメントで推奨されているように、コールバックスタイル( https://facebook.github.io/react/docs/refs-and-the-dom.html )を使用するには、プロパティの定義を追加できます。クラスで:

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; }}/>)
}
2
lucavgobbi

完全な例を欠いているので、ReactとTypeScriptを使用してユーザー入力を取得するための小さなテストスクリプトを次に示します。他のコメントとこのリンクに部分的に基づいています 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 });
        }
    });
}

}

1
Tikall

refを転送したくない場合は、PropsインターフェースでRefObject<CmpType>import React, { RefObject } from 'react';タイプを使用する必要があります

0
MiF

私はいつもこれをします

let input: HTMLInputElement = ReactDOM.findDOMNode<HTMLInputElement>(this.refs.input);

0
user2662112

Reactタイプ定義から

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

したがって、次のようにrefs要素にアクセスできます

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

refsインデックスの再定義なし。

@manakorが述べたように、あなたは次のようなエラーを得ることができます

プロパティ 'stepInput'はタイプ '{[key:string]:Component |素子; }

refを再定義する場合(使用するIDEおよびtsバージョンに依存)

TypeScriptユーザーの場合、コンストラクターは不要です。

...

private divRef: HTMLDivElement | null = null

getDivRef = (ref: HTMLDivElement | null): void => {
    this.divRef = ref
}

render() {
    return <div ref={this.getDivRef} />
}

...

0
Morlo Mbakop

別のアプローチを追加するために-refをキャストするだけです:

let myInputElement: Element = this.refs["myInput"] as Element
0