ref – https://reactjs.org/docs/refs-and-the-dom.html
There are a few good use cases for refs:
- Managing focus, text selection, or media playback.
- Triggering imperative animations.
- Integrating with third-party DOM libraries.
Refs are created using React.createRef() and attached to React JSX elements via the ref attribute. Refs are commonly assigned to an instance property when a component is constructed so they can be referenced throughout the component.
1 2 3 4 5 6 7 8 9 10 11 |
class MyComponent extends React.Component { constructor(props) { super(props); this.myRef = React.createRef(); // Refs are commonly assigned to an instance property // so they can be referenced throughout the component. } render() { // attached to React JSX elements via the ref attribute return <div ref={this.myRef} />; } } |
When a ref is passed to an element in render, a reference to the node becomes accessible at the current attribute of the ref.
1 |
const node = this.myRef.current; |
When the ref attribute is used on an HTML element, the ref created in the constructor with React.createRef() receives the underlying DOM element as its current property.
When the ref attribute is used on a custom class component, the ref object receives the mounted instance of the component as its current.
You may not use the ref attribute on function components because they don’t have instances.
In our CustomTextInput:
1) create a ref using React.createRef() and assign it to this.textInput
2) in render, assign an input control’s ref attribute to our this.textInput.
This creates a current property in our this.textInput and assigns the node of that input control to it.
3) For demo purposes, we want to show we can now control the input by programmatically putting a focus on it.
We do this by writing a method called focusTextInput. We create a button. Whenever that button is clicked, it sends
an event to our focusTextInput. In turn our focusTextInput uses our ref to programmatically put focus onto our input control.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 |
class CustomTextInput extends React.Component { constructor(props) { super(props); // create a ref to store the textInput DOM element this.textInput = React.createRef(); this.focusTextInput = this.focusTextInput.bind(this); } focusTextInput() { // Explicitly focus the text input using the raw DOM API // Note: we're accessing "current" to get the DOM node this.textInput.current.focus(); } render() { // tell React that we want to associate the <input> ref // with the `textInput` that we created in the constructor return ( <div> <input type="text" ref={this.textInput} /> <input type="button" value="Focus the text input" onClick={this.focusTextInput} /> </div> ); } } |
You can also use it on component lifecycle functions like so:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
class AutoFocusTextInput extends React.Component { constructor(props) { super(props); this.textInput = React.createRef(); } componentDidMount() { this.textInput.current.focusTextInput(); // <-- } render() { return ( <CustomTextInput ref={this.textInput} /> ); } } |
However, you can only use it on class component because there is an instance.
In functional components, you cannot use it because there is no instance:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
// create your functional component function MyFunctionComponent() { return <input />; } class Parent extends React.Component { constructor(props) { super(props); this.textInput = React.createRef(); } render() { // you CANNOT do this...X return ( <MyFunctionComponent ref={this.textInput} /> ); } } |
If you want to allow people to take a ref to your function component, you can use forwardRef.
You can, however, use the ref attribute inside a function component as long as you refer to a DOM element or a class component:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
function CustomTextInput(props) { // textInput must be declared here so the ref can refer to it const textInput = useRef(null); function handleClick() { textInput.current.focus(); } return ( <div> <input type="text" ref={textInput} /> <input type="button" value="Focus the text input" onClick={handleClick} /> </div> ); } |
Forward Refs
Ref forwarding is a feature that lets some components take a ref they receive, and pass it further down to a child.
1 2 3 4 5 6 7 8 9 |
const ButtonElement = React.forwardRef((props, ref) => ( <button ref={ref} className="CustomButton"> {props.children} </button> )); // Create ref to the DOM button: const ref = React.createRef(); <ButtonElement ref={ref}>{'Forward Ref'}</ButtonElement> |
Callback Refs
React also supports another way to set refs called “callback refs”, which gives more fine-grain control over when refs are set and unset.
Instead of passing a ref attribute created by createRef(), you pass a function. The function receives the React component instance or HTML DOM element as its argument, which can be stored and accessed elsewhere.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 |
class CustomTextInput extends React.Component { constructor(props) { super(props); this.textInput = null; this.setTextInputRef = element => { this.textInput = element; }; this.focusTextInput = () => { // Focus the text input using the raw DOM API if (this.textInput) this.textInput.focus(); }; ... ... render() { // Use the `ref` callback to store a reference to the text input DOM // element in an instance field (for example, this.textInput). return ( <div> <input type="text" ref={this.setTextInputRef} ... /> </div> ); } |