Refs is a technical term

Provides a way to access DOM or React elements

In a nutshell, it provides a way to manually retrieve and manipulate the DOM directly

For example, input element focus

File uploading function, etc

It’s the REF attribute that does the work

Noun explanation

  • ClassComponent class components
  • FunctionComponent FunctionComponent
  • The React Hook Hook
  • Callback ref Callback ref

The attribute value type varies depending on the node type to which the REF is bound

  1. The ref binding node is of type DOM element and ref represents the concrete DOM element
  2. The ref binding node type is ClassComponent and ref represents the ClassComponent (instance).
  3. The ref binding node type is FunctionComponent. Note that it cannot be bound directly
    • Because it’s not a DOM or ClassComponent
    • itselfpropsDoes not exist by defaultrefThrough theReact.forwardRefThe function must bind the DOM or ClassComponent inside it.

Create ref mode

In addition to the callback ref

Create a REF reference either way

Both contain the current attribute, which contains the ref specific value

  1. The React. CreateRef way
    • For ClassComponent, not recommended for FunctionComponent, inFunctionComponentRerender is initialized to create a new ref reference (see the difference comparison below for details)
    • The parameter cannot be passed
    • currentProperties inTypescriptThe tips forread-only
    • createRef<T>Generic functions have no default value and are set tounknow
  2. The React. UseRef way
    • React HookOne, followHookRules, for FunctionComponent or other hooks, are called at the top level of function scope
    • Can be used for data storage or performance optimization to save data tocurrentOn the properties
    • The parameter type can be arbitrary
    • Create once, update render not create only reuse
    • useRef<T = undefined>The default value for generic functions isundefined
    • currentProperty value changes cannot be detected and do not trigger the componentrenderView update
  3. callback refway
    • Resolved that ref value changes cannot be monitored
    • The ClassComponent inline binding or FunctionComponent binding is called twice when updated again, printing the first value asnull, the second time is the specific bindingnodeReact empties the old ref and sets the new one
    • In ClassComponent,
      • callback refClass when bound to an inline functionrenderCall it once, againrenderCall twice
        export default class Child extends React.PureComponent {
          state = {
            a: 100
          }
          constructor(props: any) {
            super(props)
          }
      
          onCount() {
            this.setState({
              a: Math.random()
            })
          }
      
          render() {
            return (
              <div>
                <p ref={(node: any) = >Log (node)}}>{this.state. A} {this.state.</p>
                <button className="btn btn-primary" onClick={this.onCount.bind(this)}>click</button>
              </div>)}}Copy the code
      • callback refBind instance method, initializerenderCall it once, againrenderDon’t call
      export default class Child extends React.PureComponent {
        state = {
          a: 100
        }
        cbRef: (node: any) = > void
        constructor(props: any) {
          super(props)
          this.cbRef = (node: any) = > {
            // Initialize and re-render updates, print only once
            // Result: node object
            console.log(node)
          }
        }
      
        onCount() {
          this.setState({
            a: Math.random()
          })
        }
      
        render() {
          return (
            <div>
              <p ref={this.cbRef}>{this.state.a}</p>
              <button className="btn btn-primary" onClick={this.onCount.bind(this)}>click</button>
            </div>)}}Copy the code
    • In FunctionComponent,callback refWhether the function is inline or not, initialize it and print it once, render it again and print it twice
        function User(_props: any) {
          let [data] = useState({
            foo: 1
          })
          const [count, setCount] = useState(0)
          const renderRef = (node: any) = > {
            // Initialize to print the result once: node object
            // Next render update prints two results: the first null and the second node object
            console.log(node)
          }
      
          return (
            <>
              <h3>{data.foo}</h3>
              <p ref={renderRef}>count: {count}</p>
              <button className="btn btn-primary" onClick={()= > setCount(count + 1)}>click me</button>
            </>)}export default User
      Copy the code

Ref forwarding forwardRef

FunctionComponent has no ref attribute

The parent component cannot get DOM elements directly by ref referencing FunctionComponent components

Utilize the forwardRef forwarding feature

The forwarded FunctionComponent component has the ref attribute

Bind the parent component ref to the DOM element

In the parent component, you can get the child’s specific DOM element for manipulation

function InputChild(props: any) {
  return (
    <input  type="text" ref={props.inputRef} className="form-control" placeholder="Say something." />)}const ForwardInput = forwardRef((props, ref: any) = >  <InputChild inputRef={ref} />)

function User(_props: any) {
  const ref = useRef<HTMLInputElement>()
  return (
    <>{/* The parent component sets the ref attribute by forwarding the returned component through InputChild */} {/* The parent component clicks the button to set the focus of the input element */}<ForwardInput ref={ref} />
      <button className="btn btn-primary" onClick={()= >ref? .current? .focus()}>input focus</button>
    </>)}export default User
Copy the code

Compare createRef and useRef in FunctionComponent

As shown above:

CreateRef is always null every time it renders new

UseRef is only created once and reused during rendering, so it references the same P element

The FunctionComponent recommends useRef

The source code is as follows:

function User(_props: any) {
  const ref = useRef(null)
  const ref2 = createRef<HTMLParagraphElement>()
  const [count, setCount] = useState(0)

  useEffect(() = > {

  }, [count])
  console.log(count)
  console.log('useRef:', ref, 'createRef:', ref2)
  return (
    <>
      <h3>{count}</h3>
      <p ref={ref}>useRef p</p>
      <p ref={ref2}>createRef p</p>
      <button className="btn btn-primary" onClick={()= > setCount(count + 1)}>click count</button>
    </>)}export default User
Copy the code