2015-11-19 15 views
27

私はReactでTypescriptを使用しています。私はrefsを使用する方法を理解していないので、refによって参照されている反応ノードに関して静的型付けとインテリセンスを得ることができません。私のコードは以下の通りです。Typescriptとの反応でのrefsの使用方法

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> 
    ); 
}} 

答えて

27

をつかむために、その場合 には、これを行う今ref属性は、もはや文字列が、コールバックすることを意図していること(公式ドキュメントの「Refs and the DOM」を参照してくださいし、 Issue #1373)、あなたは親クラスのプロパティを定義する必要があります。

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

     private stepInput: HTMLInputElement; 

次に、HTML要素に、そのようなref属性を設定します0

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

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

25

手動設定にある(I've been doing)片道:

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

そしてあなたも、よりよいgetter関数(例えばhere)でこれを包むことができます。

stepInput =(): HTMLInputElement => ReactDOM.findDOMNode(this.refs.stepInput); 
+0

ありがとう@basarat。私はあなたのソリューションを試しましたが、タイプ・エレメントをHTMLInputElementに代入することはできません。要素acceptは型要素にありません。 ' –

+0

新しいバージョンのreact-dom定義に問題がある可能性があります。その間にアサーションとして使用する – basarat

+0

明らかに 'any'はここで必須ではありません。ほとんどの例では、 'HTMLInputElement'を使用しています。明白なことだけを述べていますが、あなたのリファレンスがReactコンポーネント(つまり 'PeoplePicker')上にある場合、そのコンポーネントを型として使用して型を取得できます。 –

16

編集:これはもはやTypescriptでrefを使う正しい方法ではありません。 Jeff Bowenの答えを見て、それをアップビューして可視性を高める。

問題の答えが見つかりました。クラス内で以下のようにrefsを使用します。

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

正しい方向を指してくれてありがとう@basarat。完全な例を欠く

+2

私はまだ 'Property 'stepInput'がタイプ '{[key:string]に存在しません:コンポーネント |素子; } '、 'this.refs.stepInput'にアクセスしようとしています。 –

+0

@NikSumeiko、あなたの 'refs'オブジェクトに' [key:string] 'エントリしかないので、あなたはそのエラーを受けていました。 –

+1

@Ashkar [あなたの編集](https://stackoverflow.com/revisions/33826399/3)によれば、[受け入れられた回答を変更する]ことができます(https://meta.stackexchange.com/a/262069)。ありがとう! –

1

、ここに反応し、活字体で作業する場合、ユーザー入力を取得するための私の小さなテスト・スクリプトがあります。他のコメントに部分的に基づいており、このリンク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
class SelfFocusingInput extends React.Component<{ value: string, onChange: (value: string) => any }, {}>{ 
    ctrls: { 
     input?: HTMLInputElement; 
    } = {}; 
    render() { 
     return (
      <input 
       ref={(input) => this.ctrls.input = input} 
       value={this.props.value} 
       onChange={(e) => { this.props.onChange(this.ctrls.input.value) } } 
       /> 
     ); 
    } 
    componentDidMount() { 
     this.ctrls.input.focus(); 
    } 
} 

だからあなたはあなたにアクセスすることができ、型定義

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

に反応からオブジェクト

+1

あなたの答えを説明してください – AesSedai101

+0

この回答は強く型付けされた要素にctrls.inputを設定しています。これはより良い "Typescript"の選択肢です。 – Doug

0

に入れ以下の要素を参照してください。

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

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

@manakorはあなたが

プロパティ 'stepInput' タイプに存在しません「{のようなエラーを取得することができます述べたように、[キー:文字列]: コンポーネント|素子; }

あなたがのリアクトドキュメントに推奨されているように、引用文献(あなたが使用IDEとTSバージョンによって異なります)

2

がコールバックスタイル(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; }}/>) 
} 
0

ただ、別のアプローチを追加する - あなたは、単にあなたの参照をキャストすることができ、のようなもの:

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

私は常に参照

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

+0

入力します。HTMLInputElement = ReactDOM.findDOMNode (this.refs ['input']); – user2662112

関連する問題