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>
);
}}
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に感謝します。
編集:これはTypeScriptでrefを使用する正しい方法ではなくなりました。JeffBowenの答えを見て、それを支持して可視性を高めます。
問題に対する答えを見つけました。クラス内で次のようにrefを使用します。
refs: {
[key: string]: (Element);
stepInput: (HTMLInputElement);
}
正しい方向を指してくれてありがとう@basarat.
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
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; }}/>)
}
完全な例を欠いているので、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 });
}
});
}
}
ref
を転送したくない場合は、PropsインターフェースでRefObject<CmpType>
のimport React, { RefObject } from 'react';
タイプを使用する必要があります
私はいつもこれをします
let input: HTMLInputElement = ReactDOM.findDOMNode<HTMLInputElement>(this.refs.input);
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} />
}
...
別のアプローチを追加するために-refをキャストするだけです:
let myInputElement: Element = this.refs["myInput"] as Element