The Ref attribute is used toGets the node of the DOM elementandGets an instance of the child component.

Update iteration of Ref:

1, the String Ref

String Ref is an outdated API. Because String refs have some problems, they will be discarded in a future release and are not recommended.

Usage: this.refs.xxx

Get the DOM element node:

import React, { Component } from 'react';
class App extends Component {
    componentDidMount() {
        console.log('this.refs.XXX');
        console.log(this.refs.h1Ref);
    }
    render() {
        return <h1 ref='h1Ref'>Hello World! </h1> } }export default App;Copy the code

Print result:



Get instances of child components:

After Ref gets an instance of the child component, you can call a method on the child component.

import React, { Component } from 'react';
class App extends Component {
    componentDidMount() {
        console.log(this.refs.childRef);
        this.refs.childRef.handleLog(); // Child Component    }
    render() {
        return( <div> <h1>Hello World! </h1> <Child ref='childRef' count='1' />
            </div>
        )
    }
}
class Child extends Component {
    handleLog = () => {
        console.log('Child Component');
    }
    render() {
        const { count } = this.props;
        return <h2>count: { count }</h2>
    }
}
export default App;Copy the code

Print result:



2, the Callback Ref

Callback RefAllows you to more finely control when refs are set and released,
Pass a function. This function takes an instance of the React component or an HTML DOM element as an argument.

React will call the ref callback and pass in the DOM element when the component is mounted and null when it is unmounted. React ensures that the refs are up to date before componentDidMount or componentDidUpdate is triggered.

Ref ={element => (this.eleref = element)}

Get the DOM element node:

import React, { Component } from "react";
class App extends Component {
  componentDidMount() {
    console.log("Callback Ref");
    console.log(this.h1Ref);
  }
  render() {
    return (
      <div>
        <h1 ref={element => (this.h1Ref = element)}>Hello World!</h1>
      </div>
    );
  }
}
export default App;Copy the code

Print result:



Get child component instances:

import React, { Component } from "react";
class App extends Component {
  componentDidMount() {
    console.log("Callback Ref");
    console.log(this.childRef);
    this.childRef.handleLog();
  }
  render() {
    return( <div> <h1>Hello World! </h1> <Child ref={component => (this.childRef = component)} count="1" />
      </div>
    );
  }
}
class Child extends Component {
  handleLog = () => {
    console.log("Child Component");
  };
  render() {
    const { props } = this;
    return<h1>count: {props.count}</h1>; }}export default App;Copy the code

Print result:

3, Create Ref

React 16.3 releases React.createref () and is now recommended for use in class components.

Refs are created using react.createref () and attached to the React element via the ref attribute. When components are constructed, Refs are typically assigned to instance properties so that they can be referenced throughout the component.

When a ref is passed to an element in render, a reference to that node can be accessed in the ref’s current property.

React passes a DOM element to the current property when the component is mounted and a NULL value when the component is unmounted. The ref is updated before the componentDidMount or componentDidUpdate lifecycle hook is triggered.

Get the DOM element node:

import React, { Component, createRef} from "react";
class App extends Component {
  constructor(props) {
    super(props);
    this.h1Ref = createRef();
  }
  componentDidMount() {
    console.log("React.createRef()");
    console.log(this.h1Ref.current);
  }
  render() {
    return <h1 ref={this.h1Ref}>Hello World!</h1>;
  }
}
export default App;Copy the code

Print result:



Get instances of child components:

import React, { Component, createRef } from "react";
class App extends Component {
  constructor(props) {
    super(props);
    this.childRef = createRef();
  }
  componentDidMount() {
    console.log("React.createRef()");
    console.log(this.childRef.current);
    this.childRef.current.handleLog();
  }
  render() {
    return( <div> <h1>Hello World! </h1> <Child ref={this.childRef} count="1" />
      </div>
    );
  }
}
class Child extends Component {
  handleLog = () => {
    console.log("Child Component");
  };
  render() {
    const { props } = this;
    return<h1>count: {props.count}</h1>; }}export default App;Copy the code

Print result:



4, useRef

Using String Ref, Callback Ref, or Create Ref in a function component throws the following error ❌ :

Uncaught Invariant Violation: Function components cannot have refs. Did you mean to use React.forwardRef()?

Because the function component has no instance, String Ref, Callback Ref, and Create Ref are not used in the function component. UseRef is used instead.

What useRef does:

  • Gets the node of the DOM element
  • Gets an instance of the child component
  • Storage of shared data between render cycles (state cannot store data across render cycles because saving state triggers component rerendering)

Gets the node of the DOM element

import React, { useEffect, useRef } from 'react';
function App() {
  const h1Ref = useRef();
  useEffect(() => {
    console.log('useRef')
    console.log(h1Ref.current)
  }, [])
  return<h1 ref={h1Ref}>Hello World! </h1> }export default App;Copy the code

Printed results:



Get instances of child components:

Note: Since a function component has no instance, if you want to get an instance of a subcomponent using ref, write the subcomponent group as a class component.

import React, { Component, useEffect, useRef } from 'react';
function App() {
  const childRef = useRef();
  useEffect(() => {
    console.log('useRef')
    console.log(childRef.current)
    childRef.current.handleLog();
  }, [])
  return( <div> <h1>Hello World! </h1> <Child ref={childRef} count="1"/> </div>)} Class Child extends Component {handleLog = () => {console.log()'Child Component');
  }
  render() {
    const { count } = this.props;
    return <h2>count: { count }</h2>
  }
}
export default App;Copy the code

Print result:



Storage of shared data between render cycles

Class components, state cannot store components across render cycles, because each saving of the state parameter triggers a re-rendering of the component.

Scenario: Declare a parameter count = 0, increment count every second during component initialization until count > 5. Clear timer.

Set the timer to a global variable and mount it to current using useRef

import React, { useState, useEffect, useRef } from "react";
function App() {
  const [count, setCount] = useState(0); Const timer = useRef(); const timer = useRef(); UseEffect (() => {timer.current =setInterval(() => {
      setCount(count => count + 1); }, 1000); } []); UseEffect (() => {useEffect() => {if(count > 5) { clearInterval(timer.current); }});return <h1>count: {count}</h1>;
}
export default App;Copy the code