React study notes six-refs

This article is a study note I wrote when I was learning React. I will record and share it here. This is the sixth article, which mainly introduces refs in react.

Table of contents

1.Basic use of refs

1.1 String type ref small case

2. Ref in callback form

2.1 Small case of callback form ref

2.2 Problem with the number of calls in callback ref

3.createRef

3.1Usage of createRef

 3.2createRef’s “Dedicated Personnel”

4.ref summary


1.Basic use of refs

Tags within components can define ref attributes to identify themselves.

1.1 String type ref small case

First, let's write a small case to understand refs. We write a custom component and two input boxes. Clicking the button prompts the value of the first input box. When the second text box loses focus, it prompts the value of the second text box.

Proceed as follows:

        1. When the render function builds the virtual dom, we use ref to add an identifier to the input box. The first input is called input1, and the second input2 is called input2. For example

        <input ref='input1' type="text" placeholder="Click the button to prompt data"/>

Note that ref is used to add representation, not refs. Do not write an extra s.

        2. Then we set events for the corresponding button and the second input box, which are click events and focus loss events respectively. as follows:

        <button onClick={this.showData}>  <input ref='input2' onBlur={this.showData2} type="text"/>

Note that the events in react are different from those in js. For example, for the click event onclick, the first letter after on in react is capitalized to distinguish it from js. Basically, events in react are capitalized with the first letter after on.

        3. Next we write event processing functions, showData and showData2. Since we have set a ref to add a logo to the input box, the information about using ref to add a logo is all stored in the refs attribute of this component instance , so when we use it in the component, we directly use this.refs. to use the logo set by ref. It can be used by name, and it is recommended to use destructuring assignment. As follows, deconstruct and assign the refs attribute to get the input1 we want:

        const {input1} = this.refs

       In this way, input1 represents the first input box, and we can enter the content of the first text box.

code show as below:

<script type="text/babel">
        //创建组件
        class Demo extends React.Component {
            showData = ()=>{
                const {input1} = this.refs
                alert(input1.value)
            }
            showData2 = ()=>{
                const {input2} = this.refs
                alert(input2.value)
            }
            render() {
                return (//构建虚拟dom
                    <div>
                        <input ref='input1' type="text" placeholder="点击按钮提示数据"/>&nbsp;
                        <button onClick={this.showData}>点我提示左侧的数据</button>&nbsp;
                        <input ref='input2' onBlur={this.showData2} type="text" placeholder="失去焦点提示数据"/>&nbsp;
                    </div>
                )
            }

        }

        //渲染组件到界面
        ReactDOM.render(<Demo/>, document.getElementById('test1'))
    </script>

2. Ref in callback form

2.1 Small case of callback form ref

The above case is a string type refs. Although it is very simple, in the react official documentation, this method is not recommended. It will cause some efficiency problems and may even be abandoned in the future. So in the above case, we only make an introduction to learning refs.

So now let's learn about ref in callback form.

        1. We try to  change ref='input1' to an arrow function type: ref={(a)=>{console.log(a)}} . The parameter of this function is a. Then print a in the function body to see a. What is it.

        String form: <input ref='input1' type="text" placeholder="Click the button to prompt data"/>

        Function form: <input ref={(a)=>{console.log(a)}} type="text" placeholder="Click the button to prompt data"/>

Print the result:

        

 It can be seen that parameter a is the current dom node, and it is this input box that is passed in ref as a parameter. Because the arrow function does not have its own this, it will use the this of the outer render function as its own this, and the this of the reander function points to the instance constructed by the component, so this arrow function can be associated with the instance. This ref is located in The dom node is mounted on the instance and named "input1".

Therefore, it is not appropriate to call this formal parameter a. It is more suitable to call it currentNode (current node), as the name implies, or simply c. Combined with the characteristics of the arrow function, there is only one parameter, so you can omit the parentheses of the parameter, the function body is only one sentence, and you can also omit the curly braces on the right side of the arrow function. So ref is simplified as follows:

        ref={c => this.input1 = c}

2. The event function will change. It used to be const {input2} = this.refs , but now it is const {input2} = this  . Because the DOM node where this ref is located is mounted on the instance, you can just write this directly.

code show as below:

 <script type="text/babel">
        //创建组件
        class Demo extends React.Component {
            showData = () => {
                const {input1} = this
                alert(input1.value)
            }
            showData2 = () => {
                const {input2} = this
                alert(input2.value)
            }
            render() {
                return (//构建虚拟dom
                    <div>
                        <input ref={c => this.input1 = c} type="text" placeholder="点击按钮提示数据" />&nbsp;
                        <button onClick={this.showData}>点我提示左侧的数据</button>&nbsp;
                        <input ref={c => this.input2 = c} onBlur={this.showData2} type="text" placeholder="失去焦点提示数据" />&nbsp;
                    </div>
                )
            }

        }

        //渲染组件到界面
        ReactDOM.render(<Demo />, document.getElementById('test1'))
    </script>

2.2 Problem with the number of calls in callback ref

Let’s start with the code:

 class Demo extends React.Component {
            showInfo = ()=>{
                const {input1} = this
                console.log(input1);
            }
            render() {
                return (//构建虚拟dom
                    <div>
                        <input ref={c => this.input1 = c} type="text" />
                        <button onClick={this.showInfo}>点我提示输入的数据</button>
                    </div>
                )
            }

        }

        //渲染组件到界面
        ReactDOM.render(<Demo />, document.getElementById('test1'))

Then introduce the instructions on callback ref from the react official website:

        If  ref the callback function is defined as an inline function , it will be executed twice during the update process , the first time passing in the parameters  , and the second time passing in the parameter DOM element. This is because a new function instance is created on each render, so React clears the old ref and sets the new one. The above problem can be avoided by defining the callback function of ref as a bound function of the class, but in most cases it is irrelevant.null

        Note that in the code we wrote above, the ref callback function is written in the input tag. This means that the ref callback function is defined as an inline function, which is in line with the instructions on the official website. However, it will only be executed twice during the update process, once null and once passed in the parameter dom element. The first time render is executed to render the dom is initialization, not update.

        So we add a data update case to the case, let this case have an updated status, and then verify the issue of the number of callbacks. The newly added case is the case of switching between hot and cool that we have written before. In addition, print the parameter c of the callback function in the callback function of ref. code show as below:

//创建组件
        class Demo extends React.Component {
            state = { isHot: false }
            showInfo = () => {
                const { input1 } = this
                alert(input1.value)
            }
            changWeather = ()=>{
                const {isHot} = this.state
                this.setState({isHot:!isHot})
            }
            render() {
                const { isHot } = this.state
                return (//构建虚拟dom
                    <div>
                        <h2>今天天气很{isHot ? '炎热' : '凉爽'}</h2>
                        <input ref={c => {this.input1 = c;console.log('@',c)}} type="text" /><br/><br/>
                        <button onClick={this.showInfo}>点我提示输入的数据</button><br/><br/>
                        <button onClick={this.changWeather}>点我切换天气</button>
                    </div>
                )
            }

        }
        //渲染组件到界面
        ReactDOM.render(<Demo />, document.getElementById('test1'))

The effect is as follows, just open the page:

 After clicking the switch button to switch the page to display text:

         This just confirms what the official website says. When updating, the first callback function parameter is null, and the second time the dom node is passed in as a parameter. But this does not affect the normal function.

Explanation: When the page is just loaded, this situation does not happen. This is because the render function is called and the ref in the form of a callback function is found in it. Then the corresponding DOM node is passed in as a parameter according to what is written in the ref function.

        But when updating, the state will change, the state will drive the page display, and the render function will be called again. When calling render again, a callback function-style ref was found in the virtual dom, but React was not sure what parameters it received when calling this ref before, and what happened to the function execution, so it directly cleared the ref first, passed the parameter as null, and then Then call this ref and pass in the current dom node parameters.

        Avoid this problem: The official website says: The above problem can be avoided by defining the callback function of ref as the binding function of the class , but in most cases it is irrelevant.

        So what is the method of class binding function? Let’s modify the above code:

Original code:

<input ref={c => {this.input1 = c;console.log('@',c)}} type="text" />

In this way, the callback function ref is written in the dom node, which we call inline ref.

Modify this code:

<input ref={this.saveInput} type="text" />

And put the saveInput function on the instance itself.

 saveInput = (c) => {
                this.input1 = c
                console.log("@", c);
            }

This becomes the binding function method of class, which will not affect the normal operation of the function. In this case, it will not happen that it is called twice after the update, and the first time is null.

3.createRef

3.1Usage of createRef

        React.createRef is an API of react. After calling, it can return a container, which can store the node identified by ref. So when we use it, we can create a createRef container, assign it to myRef and mount it on the instance:

                myRef = React.createRef()

        Then use it directly in the corresponding tag of the render function:

                <input ref={this.myRef} type="text" />

        This is equivalent to treating the input dom node as a parameter of ref and putting this ref into the myRef container.

Let’s look at the code:

 //创建组件
        class Demo extends React.Component {
            /*
                React.createRef调用后可以返回一个容器,该容器可以存储被ref所标识的节点
            */
            myRef = React.createRef()//创建容器赋值给myRef并且挂载到实例上
            showInfo = () => {
                console.log(this.myRef);
            }
            render() {
                return (//构建虚拟dom
                    <div>
                        <input ref={this.myRef} type="text" />
                        <button onClick={this.showInfo}>点我提示输入的数据</button>
                    </div>
                )
            }
        }
        //渲染组件到界面
        ReactDOM.render(<Demo />, document.getElementById('test1'))

Let's print this.myRef to see the output: As shown in the figure, what is printed is an object, and the current inside is the input node we put into the container.

 Then print this.myRef.current: As shown in the figure, the input node is printed.

 Finally, print this.myRef.current.value: The value in the input box is printed as shown in the figure.

 

 3.2createRef’s “Dedicated Personnel”

Note that although createRef is used as a container, it is "for exclusive use" and can only be placed in a container. We can try to write a case and put two refs into the createRef container.

In the above case, we also set a createRef container for the button:

  <input ref={this.myRef} type="text" />
  <button ref={this.myRef} onClick={this.showInfo}>点我提示输入的数据</button>

And print output, console.log(this.myRef);

The result is as follows:

 Obviously, only one ref can exist in createRef, and the later one will replace the previous one.

        So we need to create several more createRefs to ensure that everyone has a createRef. We create two createRef and assign them to myRef and myRef2 respectively. Assign myRef and myRef2 to the two inputs respectively, and perform different processing on the two containers in showInfo and showInfo2.

code show as below:

//创建组件
        class Demo extends React.Component {
            /*
                React.createRef调用后可以返回一个容器,该容器可以存储被ref所标识的节点
            */
            myRef = React.createRef()//创建容器赋值给myRef并且挂载到实例上
            myRef2 = React.createRef()
            showInfo = () => {
                alert(this.myRef.current.value);
                console.log(this.myRef);
            }
            showInfo2 = () => {
                alert(this.myRef2.current.value)
            }
            render() {
                return (//构建虚拟dom
                    <div>
                        <input ref={this.myRef} type="text" placeholder="点击按钮提示内容" />
                        <button onClick={this.showInfo}>点我提示输入的数据</button>
                        <input ref={this.myRef2} onBlur={this.showInfo2} type="text" placeholder="失去焦点提示内容" />
                    </div>
                )
            }
        }
        //渲染组件到界面
        ReactDOM.render(<Demo />, document.getElementById('test1'))

In this way, it can be used normally when multiple createRef containers are needed. But there are also disadvantages, that is, several createRefs are used in the reander function, and several createRefs need to be created in the above example. But this createRef is still the most recommended way to use ref officially in react.

4.ref summary

After learning how to use three refs, let’s summarize:

1. Try to avoid using ref in string form, but even if you write ref in string form, there won't be much problem.

2. The ref in callback form is a little more troublesome. Don't worry too much about the number of callback executions of the callback function. Inline callback functions can be written. The official website says: define the callback function of ref as the binding function of the class, but in most cases it does not matter.

3.createRef is the most troublesome, but currently it is the most recommended by react officials.

Guess you like

Origin blog.csdn.net/zhangawei123/article/details/130799946