score:280
If you’re using React 16.3+, the suggested way to create refs is using 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} />;
}
}
When the component mounts, the ref
attribute’s current
property will be assigned to the referenced component/DOM element and assigned back to null
when it unmounts. So, for example, you can access it using this.stepInput.current
.
For more on RefObject
, see @apieceofbart's answer or the PR createRef()
was added in.
If you’re using an earlier version of React (<16.3) or need more fine-grained control over when refs are set and unset, you can use “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} />
}
}
When the component mounts, React will call the ref
callback with the DOM element, and will call it with null
when it unmounts. So, for example, you can access it simply using this.stepInput
.
By defining the ref
callback as a bound method on the class as opposed to an inline function (as in a previous version of this answer), you can avoid the callback getting called twice during updates.
There used to be an API where the ref
attribute was a string (see Akshar Patel's answer), but due to some issues, string refs are strongly discouraged and will eventually be removed.
Edited May 22, 2018 to add the new way of doing refs in React 16.3. Thanks @apieceofbart for pointing out that there was a new way.
score:-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();
}
}
put them in an object
score:0
Lacking a complete example, here is my little test script for getting user input when working with React and TypeScript. Based partially on the other comments and this link 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 });
}
});
}
}
score:0
From React type definition
type ReactInstance = Component<any, any> | Element;
....
refs: {
[key: string]: ReactInstance
};
So you can access you refs element as follow
stepInput = () => ReactDOM.findDOMNode(this.refs['stepInput']);
without redefinition of refs index.
As @manakor mentioned you can get error like
Property 'stepInput' does not exist on type '{ [key: string]: Component | Element; }
if you redefine refs(depends on IDE and ts version you use)
score:0
Just to add a different approach - you can simply cast your ref, something like:
let myInputElement: Element = this.refs["myInput"] as Element
score:0
I always do this, in that case to grab a ref
let input: HTMLInputElement = ReactDOM.findDOMNode<HTMLInputElement>(this.refs.input);
score:1
For typescript user no constructor required.
...
private divRef: HTMLDivElement | null = null
getDivRef = (ref: HTMLDivElement | null): void => {
this.divRef = ref
}
render() {
return <div ref={this.getDivRef} />
}
...
score:1
If you wont to forward your ref
, in Props interface you need to use RefObject<CmpType>
type from import React, { RefObject } from 'react';
score:2
To use the callback style (https://facebook.github.io/react/docs/refs-and-the-dom.html) as recommended on React's documentation you can add a definition for a property on the class:
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; }}/>)
}
score:2
For those looking on how to do it when you have an array of elements:
const textInputRefs = useRef<(HTMLDivElement | null)[]>([])
...
const onClickFocus = (event: React.BaseSyntheticEvent, index: number) => {
textInputRefs.current[index]?.focus()
};
...
{items.map((item, index) => (
<textInput
inputRef={(ref) => textInputs.current[index] = ref}
/>
<Button
onClick={event => onClickFocus(event, index)}
/>
}
score:16
EDIT: This is no longer the right way to use refs with Typescript. Look at Jeff Bowen's answer and upvote it to increase its visibility.
Found the answer to the problem. Use refs as below inside the class.
refs: {
[key: string]: (Element);
stepInput: (HTMLInputElement);
}
Thanks @basarat for pointing in the right direction.
score:28
If you're using React.FC
, add the HTMLDivElement
interface:
const myRef = React.useRef<HTMLDivElement>(null);
And use it like the following:
return <div ref={myRef} />;
score:33
One way (which I've been doing) is to setup manually :
refs: {
[string: string]: any;
stepInput:any;
}
then you can even wrap this up in a nicer getter function (e.g. here):
stepInput = (): HTMLInputElement => ReactDOM.findDOMNode(this.refs.stepInput);
score:34
Since React 16.3 the way to add refs is to use React.createRef as Jeff Bowen pointed in his answer. However you can take advantage of Typescript to better type your ref.
In your example you're using ref on input element. So they way I would do it is:
class SomeComponent extends React.Component<IProps, IState> {
private inputRef: React.RefObject<HTMLInputElement>;
constructor() {
...
this.inputRef = React.createRef();
}
...
render() {
<input type="text" ref={this.inputRef} />;
}
}
By doing this when you want to make use of that ref you have access to all input methods:
someMethod() {
this.inputRef.current.focus(); // 'current' is input node, autocompletion, yay!
}
You can use it on custom components as well:
private componentRef: React.RefObject<React.Component<IProps>>;
and then have, for example, access to props :
this.componentRef.current.props; // 'props' satisfy IProps interface
score:81
React.createRef
(class comp.)
class ClassApp extends React.Component {
inputRef = React.createRef<HTMLInputElement>();
render() {
return <input type="text" ref={this.inputRef} />
}
}
React.useRef
(Hooks / function comp.)
a) Use readonly refs for React-managed DOM nodes:
const FunctionApp = () => {
// note the passed-in `null` arg ----------------v
const inputRef = React.useRef<HTMLInputElement>(null)
return <input type="text" ref={inputRef} />
}
inputRef.current
becomes a readonly
property by initializing its value with null
.
const FunctionApp = () => {
const renderCountRef = useRef(0)
useEffect(() => {
renderCountRef.current += 1
})
// ... other render code
}
Note: Don't initialize useRef
with null
in this case - it would make the renderCountRef
type readonly
(see example). If you need to provide null
as initial value, do this:
const renderCountRef = useRef<number | null>(null)
Callback refs (both)
// Function component example, class analogue
const FunctionApp = () => {
const handleDomNodeChange = (domNode: HTMLInputElement | null) => {
// ... do something with changed dom node.
}
return <input type="text" ref={handleDomNodeChange} />
}
Note: String Refs are considered legacy and omitted for the scope of this answer.
Source: stackoverflow.com
Related Query
- How to use refs in React with Typescript
- How to use Refs with Material-ui 4, React 16.8, TypeScript 3.5
- How to use React refs with new Typescript strictPropertyInitialization option?
- How to use React with Typescript and SASS
- How to use forwardRef with FunctionComponent in React Native using TypeScript
- How to use Material UI custom theme in React with Typescript
- how to use .env file in a react js with typescript project?
- How to use jest.spyOn with React function component using Typescript
- How do you correctly use React.lazy() in Typescript to import a react component with a generic type parameter?
- React how to use icon inside Textfield Material-UI with TypeScript
- How to use Material UI custom variants in React with Typescript
- How to use emotion/styled with React and Typescript
- How to use radium in React typescript (Error: has no properties in common with type 'CSSProperties'. TS2559)?
- How to use React Hook Form with Typescript (Input Component)
- How to use react-datetime with react + typescript (inside tsx)
- How to use useState hook in React with typescript correctly?
- How to use PropTypes with Typescript in React
- How to use mixins with Typescript and React JSX (TSX)
- How to use Typescript with React Router and match
- How to properly use TypeScript types with a Styled Component canvas on React
- How to use TypeScript with React / Redux mergeProps
- How to use Facebook Javascript SDK to login and force re-authentication with React Web and Typescript inside of a component
- How to Use Next.Js "Link" element as a custom React component with Typescript
- How to use Typescript Transform with React
- How to use SignaturePad with React TypeScript
- How to use TypeScript generics with React render props
- How to use Sigma.js in React with Typescript
- How can I use multiple refs for an array of elements with hooks?
- How to use callback with useState hook in react
- How to use children with React Stateless Functional Component in TypeScript?
More Query from same tag
- React.js: How to append a component on click?
- console.log not working in react and graphql
- Onclick an element that changes the state of another element
- React API returns empty
- How to map out preloaded images from an array in react?
- Where to put timeout operator in Redux Observable fetching epic
- React: 404 Found when importing local images
- React Typescript No index signature with a parameter of type 'string' was found on type
- Forcing a div to be full page height without using 100vh
- Reformat array of objects
- Making request parameter optional in axios get request
- TypeError: Cannot read properties of undefined (reading 'map') - State returns undefined
- Get value from One function and pass it to another
- React: Child component is passing it's state up to parent, but once parent has it, the parent is not updating its state
- Unexpected token i in JSON at position 6 - react redux app
- Dynamically inject data in React Router Routes
- How to conditionally apply an onClick listener depending on state
- Apply Class if Child element exist in a loop for mega menu with React
- button onclick refresh page instead of set state to false
- Error after changing let to const and changing i++ with i+1 in a for loop
- Duplicate data validation on material tabel column in React
- How to update the state of child components to drag them around independently
- How to fix "react/jsx-closing-bracket-location" in WebStorm
- API data is not fetched in reactJS
- react-testing-library input change test always passing
- How to include textarea field when defining model of a contact us form in react web application
- How to adjust height of div based on content
- Why does asynchronous function cause PropTypes to be null
- Fire (dispatch) custom event with react-testing-library
- How does using loaders in webpack affect your build file?