I\'m using Typescript with React. I\'m having trouble understanding how to use refs so as to get static typing and intellisense with respect to the react nodes referenced by
If you wont to forward your ref
, in Props interface you need to use RefObject<CmpType>
type from import React, { RefObject } from 'react';
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
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} />;
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)}
/>
}
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.
I always do this, in that case to grab a ref
let input: HTMLInputElement = ReactDOM.findDOMNode<HTMLInputElement>(this.refs.input);