2015-11-19 99 views
27

我正在使用React的Typescript。我無法理解如何使用refs,以便相對於refs引用的反應節點獲得靜態類型和智能感知。我的代碼如下。如何在與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像這樣:

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

組件裝入後,React將調用ref回調與DOM元素,並將其卸載時調用它與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。屬性接受缺失類型元素'' –

+0

可能是反應dom定義的較新版本的問題。在此期間用作斷言 – basarat

+0

顯然,這裏並不強制使用「任何」。我看到的大多數例子都使用'HTMLInputElement'。只需說明顯而易見的內容,但如果您的引用位於React組件(即'PeoplePicker')上,則可以使用該組件作爲類型來獲取類型。 –

16

編輯:這不再是正確的方式來使用與Typescript的參考。看看Jeff Bowen的回答,並提高它的知名度。

找到了問題的答案。在課堂內使用下面的refs。

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

感謝@basarat指向正確的方向。

+2

我仍然在類型'{[key:string]'上不存在'屬性'stepInput':組件 |元件; }',當試圖訪問'this.refs.stepInput'時。 –

+0

@NikSumeiko,你得到的錯誤是因爲你的'refs'對象只有'[key:string]'項。 –

+1

@Ashkar,根據[您的編輯](https://stackoverflow.com/revisions/33826399/3),您可以[更改接受的答案](https://meta.stackexchange.com/a/262069)。謝謝! –

1

由於缺乏一個完整的示例,下面是使用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
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(); 
    } 
} 

把它們放在一個對象

+1

請解釋你的答案 – AesSedai101

+0

這個答案是將ctrls.input設置爲強類型的元素,這是強類型的方式。這是一個更好的「Typescript」選擇。 – Doug

0

從陣營類型定義

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

所以,你可以訪問你refs元素如下

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

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

相關問題