How to deeply understand React's ref attribute

How to deeply understand React's ref attribute

Overview

First of all, Refs and ref are two concepts. Refs is an object provided by React that can be created using a specific API. The structure of this object is as follows:

This object has only one attribute, which is current. So what is this object used for?

Refs allow us to access DOM nodes or React elements created in the render method. (DOM nodes refer to native DOM elements, and the React elements created in the render() method refer to React class component elements)

We can imagine such a requirement, two brother elements, one is div and the other is button. Now I want to change the background color of the div by clicking the button. In native DOM technology, we can use document.querySelector('xxx') in the button click function to select the div node and then change its background style. However, whether in frameworks such as Vue or React, page elements are generated dynamically and cannot be obtained using the DOM API. Moreover, most of the elements operated in React are not native DOM elements, but React elements. So how do you select a native DOM element or React element?

In fact, in theory, we don’t need to perform any selection operations, as this will lose the concept of component independence in the front-end framework. Generally, events are handled through component communication. In the above situation, you can use EventBus to communicate with components. Trigger custom events in the button click event, listen to custom events in the div, and let the button notify the div to change the background color in the form of event notification, instead of directly obtaining the div for operation in the button event.

But React provides us with a way to directly access DOM elements and React elements, that is, through Refs. The way to use it is very simple, that is, add a ref attribute to the element you want to access, and attach the Refs object to the ref attribute. Then the current attribute of the Refs object is no longer empty, but the corresponding DOM element or React element instance.

1. Creation of Refs object

In React, there are two ways to create Ref objects:

1.1 React.createRef()

React.createRef() creates a Ref object, which can be accessed by attaching it to the ref attribute.
This method can be used in both function components and class components.

1.2 React.useRef(initialValue)

After adding Hook in React 16.8, there is another Hook that can create Ref objects. That is, React.useRef(initialValue).
useRef returns a mutable ref object whose .current property is initialized to the passed argument (initialValue). The returned ref object remains unchanged throughout the lifecycle of the component.
This method can only be used in function components.

2. Use of the ref attribute

The ref attribute can only be added to native DOM elements or React class components. You cannot use the ref attribute on function components because function components do not have instances.

If you want to use the ref attribute on a function component, you can forward the Ref to the native DOM element inside the function component through React.forwardRef.

2.1 Add ref to native DOM elements

Inside a class component

class App extends React.Component {
    constructor(props){
        super(props)
        this.myRef = React.createRef()
    } 
    componentDidMount(){
        console.log(this.myRef)
        console.log(this.myRef.current)
    }
    render(){
        return (
            <div ref={this.myRef}>I am the App component</div>
        )
    }
}

Inside a function component

const App = ()=>{
    const myRef = React.useRef(null)
    //const myRef = React.createRef() Both ways of creating ref objects can be React.useEffect(()=>{
        console.log(myRef)
        console.log(myRef.current)
    },[]) //Simulation life cycle return (
        <div ref={myRef}>I am the div that uses ref inside the function component</div>
    )
}

2.2 Add ref to class component

class ClassChild extends React.Component{
    render(){
        return (
            <div>I am the class child component ClassChild of the App component</div>
        )
    }
}

class App extends React.Component {
    constructor(props){
        super(props)
        this.myRef = React.createRef()
    } 
    componentDidMount(){
        console.log(this.myRef)
        console.log(this.myRef.current)
    }
    render(){
        return (
            <ClassChild ref={this.myRef}/>
        )
    }
}

2.3 Add ref to the native DOM element forwarded by the class component

The principle of ref forwarding is to pass the ref object defined in the parent component to the child component as a normal attribute, and then the child component receives it through props and assigns it to its own DOM element.

class ClassChild extends React.Component{
    render(){
        return (
            <div ref={this.props.refProp}>I am the class child component ClassChild of the App component</div> //Added ref
        )
    }
}

class App extends React.Component {
    constructor(props){
        super(props)
        this.myRef = React.createRef()
    } 
    componentDidMount(){
        console.log(this.myRef)
        console.log(this.myRef.current)
    }
    render(){
        return (
            <ClassChild refProp={this.myRef}/> // passed as a normal property)
    }
}

2.4 Add ref to the native DOM element forwarded by the function component

According to the principle of class component forwarding, the implementation method I thought of is as follows:

const FunChild = (props)=>{
    return (
        <div ref={props.refProp}>I am a function component FunChild</div>
    )
}
class App extends React.Component {
    constructor(props){
        super(props)
        this.myRef = React.createRef()
    } 
    componentDidMount(){
        console.log(this.myRef)
        console.log(this.myRef.current)
    }
    render(){
        return (
            <FunChild refProp={this.myRef}/>
        )
    }
}

This implementation is possible, but it is not the way to use the ref attribute directly on the function component. React provides a way to use ref directly on the function component, which is to use React.forwardRef to create a React element.

React.forwardRef

const FunChild = React.forwardRef((props, ref)=>{
    return (
        <div ref={ref}>I am the function component FunChild</div>
    )
}) // Use React.forwardRef to transform the function component class App extends React.Component{
    constructor(props){
        super(props)
        this.myRef = React.createRef()
    } 
    componentDidMount(){
        console.log(this.myRef)
        console.log(this.myRef.current)
    }
    render(){
        return (
            <FunChild ref={this.myRef}/> // Pass ref directly to the function component
        )
    }
}

It feels like React.forwardRef just extracts the ref attribute from props alone.
Although the above method implements the use of ref attributes on function components, the Ref object at this time is the native DOM element or other class component inside the function component being accessed. In other words, the function component here only plays a forwarding role.

3. Callback Refs

In the above methods, we create a Ref object and mount it to a native DOM element or class component through the ref attribute to access the element or instance.
In fact, the ref attribute can receive a callback function in addition to a Ref object.
When the ref attribute receives a Ref object, its corresponding DOM element or class component instance is directly assigned to the current attribute in the Ref object. When the ref attribute receives a callback function, the callback function is called with its corresponding DOM element or class component instance as the parameter of the callback function.
Therefore, we can use callback Refs without relying on Ref objects and more flexibly control the elements or instances to be accessed.

class App extends React.Component {
    constructor(props){
        super(props)
        this.myRef = null
        this.setMyRef = (element)=>{
            this.myRef = element
        }
    } 
    componentDidMount(){
        console.log(this.myRef)
    }
    render(){
        return (
            <div ref={this.setMyRef}>I am the App component</div>
        )
    }
}

The above is the details of how to deeply understand React’s ref attribute. For more information about deeply understanding React’s ref attribute, please pay attention to other related articles on 123WORDPRESS.COM!

You may also be interested in:
  • In-depth understanding of the three core properties of React
  • Detailed explanation of the use of Refs in React's three major attributes
  • Detailed explanation of the use of props in React's three major attributes
  • Detailed explanation of the use of state in React's three major attributes
  • Do you know the three major properties of React?

<<:  Tomcat components illustrate the architectural evolution of a web server

>>:  Nginx proxy axios request and precautions

Recommend

JavaScript function syntax explained

Table of contents 1. Ordinary functions 2. Arrow ...

MySQL Basics in 1 Hour

Table of contents Getting Started with MySQL MySQ...

How to change the color of the entire row (tr) when the mouse stops in HTML

Use pure CSS to change the background color of a ...

HTML5+CSS3 coding standards

The Golden Rule No matter how many people are wor...

nginx proxy_cache batch cache clearing script introduction

Preface: I used the official nginx proxy_cache as...

How to modify the initial password of MySQL on MAC

Problem description: I bought a Mac and installed...

Does the website's text still need to be designed?

Many people may ask, does the text on the website...

Pure CSS to achieve hover image pop-out pop-up effect example code

Implementation principle The main graphics are co...

How to use MySQL group by and order by together

Suppose there is a table: reward (reward table), ...

jQuery implements dynamic tag event

This article shares the specific code of jQuery t...

A brief analysis of the use of the HTML webpack plugin

Using the html-webpack-plugin plug-in to start th...

Baidu Input Method opens API, claims it can be ported and used at will

The relevant person in charge of Baidu Input Metho...

JavaScript canvas realizes colorful sun halo effect

This article example shares the specific code of ...