2015-11-19 10 views
27

Ich verwende Typoskript mit React. Ich habe Probleme zu verstehen, wie man refs verwendet, um statische Typisierung und IntelliSense in Bezug auf die reaktiven Knoten zu erhalten, auf die die refs verweisen. Mein Code ist wie folgt.Verwendung von Refs in Reaktion auf Typoskript

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

Antwort

27

Nun, da das ref Attribut greifen soll eine Zeichenfolge sein, aber ein Rückruf („Refs and the DOM“ in den offiziellen Dokumenten sehen und Issue #1373), sollten Sie eine Eigenschaft auf der übergeordneten Klasse definieren:

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

     private stepInput: HTMLInputElement; 

Dann wird auf dem HTML-Elemente, wie so das ref Attribut:

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

Sobald die Komponente geladen ist, ruft React den Callback ref mit dem DOM-Element auf und ruft es beim Aushängen mit null auf. So können Sie einfach auf this.stepInput zugreifen.

25

Eine Möglichkeit (die I've been doing) manuell zu installieren:

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

dann können Sie auch diese in einer schöneren Getter Funktion einpacken (zB here):

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

Danke @basarat. Ich habe versucht, Ihre Lösung, aber ich bekomme diesen Fehler 'Typ Element ist nicht zu Typ' HTMLInputElement zuweisen. Eigenschaft accept fehlt im Typ Element '' –

+0

Möglicherweise ein Problem mit der neueren Version der reac-dom-Definitionen. Verwendung als Assertion in der Zwischenzeit – basarat

+0

Offensichtlich ist 'any' hier nicht zwingend erforderlich. Die meisten Beispiele, die ich sehe, verwenden 'HTMLInputElement'. Wenn Sie nur das Offensichtliche angeben, aber wenn Ihr Verweis auf einer React-Komponente (d. H. 'PeoplePicker') steht, können Sie diese Komponente als Typ verwenden, um Typisierungen zu erhalten. –

16

EDIT: Dies ist nicht mehr der richtige Weg, Refs mit Typescript zu verwenden. Sehen Sie sich die Antwort von Jeff Bowen an und verbessern Sie die Sichtbarkeit.

Die Antwort auf das Problem gefunden. Verwenden Sie Refs wie unten in der Klasse.

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

Danke @basarat für das Zeigen in die richtige Richtung.

+2

Ich bekomme immer noch 'Eigenschaft 'stepInput' existiert nicht auf Typ '{[key: string]: Komponente | Element; } '', wenn Sie versuchen, auf' this.refs.stepInput' zuzugreifen. –

+0

@NikSumeiko, Sie erhielten diesen Fehler, weil Ihr 'refs' Objekt nur den' [key: string] 'Eintrag hatte. –

+1

@Ashkar, per [Ihre Bearbeitung] (https://Stackoverflow.com/revisions/33826399/3) können Sie [die akzeptierte Antwort ändern] (https://meta.stackexchange.com/a/262069). Vielen Dank! –

1

Es fehlt ein vollständiges Beispiel, hier ist mein kleines Testskript, um Benutzereingaben zu erhalten, wenn Sie mit React und TypeScript arbeiten. teilweise auf die anderen Kommentare und diesen Link Basierend 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(); 
    } 
} 

sie in einem Objekt setzen

+1

Bitte erläutern Sie Ihre Antwort – AesSedai101

+0

Diese Antwort setzt ctrls.input auf ein stark typisiertes Element, das ist der stark typisierte Weg zu gehen. Dies ist eine bessere "Typoskript" -Auswahl. – Doug

0

Von React Typdefinition

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

So können Sie Sie zugreifen Refs Element wie folgt

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

ohne Neudefinition des Refs-Index.

Wie @manakor erwähnt Sie Fehler wie

Property 'stepInput' bekommen existiert nicht auf Typ ‚{[key: string]: Komponente | Element; }

wenn Sie Refs (abhängig von der IDE und ts-Version verwenden Sie) neu definieren

2

den Callback-Stil zu verwenden (https://facebook.github.io/react/docs/refs-and-the-dom.html) als auf Reagieren der Dokumentation empfohlen, dass Sie eine Definition für eine Eigenschaft auf der Klasse hinzufügen:

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

einfach einen anderen Ansatz zu addieren - Sie einfach Ihre ref wie, etwas abgeben können:

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

ich dies immer tun, in diesem Fall einen Ref nicht mehr ist

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

+0

Eingabe lassen: HTMLInputElement = ReactDOM.findDOMNode (this.refs ['input']); – user2662112

Verwandte Themen