如何在与Typecript的React中使用引用

时间:2015-11-19 05:54:26

标签: reactjs typescript

我正在使用带有React的Typescript。我无法理解如何使用refs以获得关于refs引用的react节点的静态类型和intellisense。我的代码如下。

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

14 个答案:

答案 0 :(得分:110)

如果您使用的是React 16.3 +,则创建引用的suggested way正在使用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's answerthe PR createRef()

如果您使用的是早期版本的React(&lt; 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回调定义为类的绑定方法而不是内联函数(如此答案的previous version),可以避免回调getting called twice during更新

used to be API,ref属性是一个字符串(请参阅Akshar Patel's answer),但由于some issues,强烈建议不要使用字符串引用并最终将被删除。

编辑于2018年5月22日,在React 16.3中添加了做refs的新方法。感谢@apieceofbart指出有一种新的方式。

答案 1 :(得分:26)

一种方式(I've been doing)是手动设置的:

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

然后你甚至可以用更好的getter函数包装它(例如here):

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

答案 2 :(得分:17)

编辑:这不再是使用带有Typescript的refs的正确方法。看看杰夫鲍文的答案,并提出它以提高其知名度。

找到问题的答案。在课堂上使用如下所示的参考。

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

感谢@basarat指向正确的方向。

答案 3 :(得分:13)

从React 16.3开始,添加引用的方法是使用React.createRef,因为Jeff Bowen在他的回答中指出。但是,您可以利用Typescript来更好地输入您的参考。

在您的示例中,您使用ref on input元素。所以他们这样做的方式是:

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

    ...

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

当您想要使用该引用时,您可以访问所有输入方法:

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

答案 4 :(得分:11)

如果您使用的是React.FC,请添加HTMLDivElement界面:

const myRef = React.useRef<HTMLDivElement>(null);

并按如下所示使用它:

return <div ref={myRef} />;

答案 5 :(得分:2)

要使用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; }}/>)
}

答案 6 :(得分:1)

缺少一个完整的示例,这是我在使用React和TypeScript时获取用户输入的小测试脚本。部分基于其他评论和此链接https://medium.com/@basarat/strongly-typed-refs-for-react-typescript-9a07419f807#.cdrghertm

x = elements.delete_if do |el|
  ['pl', 'cres', 'ave'].include?(el[:streetAddress].downcase.split.last)
end

}

答案 7 :(得分:1)

对于那些在您拥有一系列元素的情况下如何进行操作的人:

from backtesting import Backtest, Strategy, Position
from backtesting.lib import crossover, SignalStrategy
from backtesting.test import SMA

class Scalp_buy(Strategy):

    start = 125
    lot_step = 5
    buy_criteria = 1
    sell_criteria = 1
    max_open = 10
    lot_size = 6000
    max_loss = 1000
    equity_list = []
    current_buy_order = []
    current_sell_order = []
    current_buy = start - buy_criteria
    current_sell = start + sell_criteria

    def init(self):
        super().init()
        self.current_buy = self.start - self.buy_criteria
        self.current_sell = self.start + self.sell_criteria
        self.buy(price = self.start, tp = self.current_sell)

    def next(self):
        super().next()
        for x in range(0,self.max_open): 
            self.orders.set_entry(price = self.current_buy)
            self.orders.set_tp(price = self.current_sell)
            self.current_buy  += self.buy_criteria
            self.current_sell  += self.sell_criteria

       # print(self.position.open_time,self.position.open_price,self.position.pl, self.position.pl_pct , self.position.size)


bt = Backtest(df, Scalp_buy, cash=10000, commission=.0014)

output = bt.run()
output```

答案 8 :(得分:0)

来自React类型定义

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

所以你可以按照以下方式访问refs元素

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

没有重新定义refs索引。

正如@manakor所提到的,你可以得到像

这样的错误
  

财产&#39; stepInput&#39;类型&#39; {[key:string]上不存在:   组件|元件; }

如果您重新定义refs(取决于您使用的IDE和ts版本)

答案 9 :(得分:0)

只是添加一种不同的方法 - 你可以简单地转换你的引用,例如:

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

答案 10 :(得分:0)

在这种情况下,我总是这样做 抓住一个参考

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

答案 11 :(得分:0)

对于打字稿用户,不需要构造函数。

...

private divRef: HTMLDivElement | null = null

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

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

...

答案 12 :(得分:0)

如果您不转发ref,则在Props界面中,您需要使用RefObject<CmpType>中的import React, { RefObject } from 'react';类型

答案 13 :(得分:-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();
    }
}

将它们放在一个对象中