with starter react not microsoft create cra app reactjs typescript

reactjs - starter - Cómo usar referencias en React with Typecript



react with typescript or not (12)

Estoy usando Typecript con React. Tengo problemas para entender cómo usar las referencias para obtener un tipeo estático e inteligencia con respecto a los nodos de reacción a los que hacen referencia las referencias. Mi código es el siguiente.

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


A falta de un ejemplo completo, aquí está mi pequeño script de prueba para obtener la entrada del usuario cuando trabaja con React y TypeScript. Basado parcialmente en los otros comentarios y este enlace 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 }); } }); }

}


De la definición de tipo React

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

Para que pueda acceder a su elemento de referencia de la siguiente manera

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

sin redefinir el índice de referencia.

Como @manakor mencionó, puede obtener un error como

La propiedad ''stepInput'' no existe en el tipo ''{[clave: cadena]: Componente | Elemento; }

si redefine las referencias (depende del IDE y la versión de TS que use)


Desde React 16.3, la forma de agregar referencias es usar React.createRef como Jeff Bowen señaló en su respuesta. Sin embargo, puede aprovechar Typecript para escribir mejor su referencia.

En su ejemplo, está utilizando ref en el elemento de entrada. Entonces, la forma en que lo haría es:

class SomeComponent extends React.Component<IProps, IState> { private inputRef: React.RefObject<HTMLInputElement>; constructor() { ... this.inputRef = React.createRef(); } ... render() { <input type="text" ref={this.inputRef} />; } }

Al hacer esto cuando desea hacer uso de esa referencia, tiene acceso a todos los métodos de entrada:

someMethod() { this.inputRef.current.focus(); // ''current'' is input node, autocompletion, yay! }

También puede usarlo en componentes personalizados:

private componentRef: React.RefObject<React.Component<IProps>>;

y luego tener, por ejemplo, acceso a accesorios:

this.componentRef.current.props; // ''props'' satisfy IProps interface


Para el usuario mecanografiado no se requiere constructor.

...

private divRef: HTMLDivElement | null = null getDivRef = (ref: HTMLDivElement | null): void => { this.divRef = ref } render() { return <div ref={this.getDivRef} /> }

...


Para usar el estilo de devolución de llamada ( https://facebook.github.io/react/docs/refs-and-the-dom.html ) como se recomienda en la documentación de React, puede agregar una definición para una propiedad en la clase:

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


Si no va a reenviar su ref , en la interfaz de Props debe usar el tipo RefObject<CmpType> de import React, { RefObject } from ''react'';


Si usa React 16.3+, la forma sugerida de crear referencias es usando 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} />; } }

Cuando el componente se monta, la propiedad current del atributo ref se asignará al componente / elemento DOM referenciado y se asignará nuevamente a null cuando se desmonte. Entonces, por ejemplo, puede acceder usando this.stepInput.current .

Para obtener más información sobre RefObject , consulte la respuesta de @ apieceofbart o se agregó PR createRef() .

Si está utilizando una versión anterior de React (<16.3) o necesita un control más detallado sobre cuándo las referencias están configuradas y no, puede usar "referencias de devolución de llamada" .

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} /> } }

Cuando el componente se monta, React llamará a la devolución de llamada de ref con el elemento DOM y lo llamará con null cuando se desmonte. Entonces, por ejemplo, puede acceder a él simplemente usando this.stepInput .

Al definir la devolución de llamada de ref como un método enlazado en la clase en lugar de una función en línea (como en una versión anterior de esta respuesta), puede evitar que la devolución de llamada se llame dos veces durante las actualizaciones.

Solía ​​haber una API donde el atributo de ref era una cadena (ver la respuesta de Akshar Patel ), pero debido a some issues , las referencias de cadena se desaconsejan y eventualmente se eliminarán.

Editado el 22 de mayo de 2018 para agregar la nueva forma de hacer referencias en React 16.3. Gracias @apieceofbart por señalar que había una nueva forma.


Siempre hago esto, en ese caso para tomar una referencia

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


Solo para agregar un enfoque diferente: simplemente puede emitir su referencia, algo como:

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


Una forma (que he estado haciendo ) es configurarlo manualmente:

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

entonces incluso puede envolver esto en una función getter más agradable (por ejemplo, here ):

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


EDITAR: Esta ya no es la forma correcta de usar referencias con Typecript. Mira la respuesta de Jeff Bowen y vota para aumentar su visibilidad.

Encontré la respuesta al problema. Use referencias como se muestra a continuación dentro de la clase.

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

Gracias @basarat por apuntar en la dirección correcta.


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

ponerlos en un objeto