How does React clear the old ref when calling ref callback after re-render?
Asked Answered
P

6

10

As the React documentation mentions:

If the ref callback is defined as an inline function, it will get called twice during updates, first with null and then again with the DOM element. This is because a new instance of the function is created with each render, so React needs to clear the old ref and set up the new one.

I can understand that the el is set to null, because we need to free the old dom node's memory after the re-render. But, there are 2 questions I still can't figure out.

  1. Why must React first call the old ref callback with null here? Couldn't it just call the newer ref callback with the new dom node?
  2. How does React clear the old ref? Does it have something to do with calling ref callback twice?
Pt answered 4/4, 2023 at 8:41 Comment(0)
F
3

You can think about ref resetting for callback ref as an effect. It's not that way but I think the rewording of the problem does help with understanding.

useEffect(() => {
  ref.current = element

  return () => {
    ref.current = null
  }
})

Let's say you pass your ref callback to a DOM node:

<div ref={(element) => console.log(element)} />

Thinking in terms of the effect gives you:

  1. when the component mounts, it calls the ref callback with that element
  2. when the component unmounts, it calls the ref callback with null because that's the "cleanup"
  3. when the component changes, it first calls the "cleanup" and then it sets up the new "effect".

Again, this is not to say that it is using a real useEffect, but the idea behind it is the same.

Few answered 4/4, 2023 at 8:46 Comment(2)
But for this case, when the component changes, it just call the ref callback with the new element after setting it. I mean it just be called one time.Pt
It could be implemented by calling once, but using this solution is probably lower mental overhead - it makes it more the same with the rest.Few
S
0

When React calls the ref callback, it needs to know whether it is setting a new ref or removing an old one.
By calling the old ref callback with a null argument, React signals to the callback that the reference to the previous element should be cleared.

Scurry answered 4/4, 2023 at 9:23 Comment(1)
This is about clearing the old element. But how React clear the old ref (that ref callback)? Does it has something to do with calling ref callback twice?Pt
F
0

Example Code:-

import React, { useRef, useEffect } from 'react'

const AudioPlayer = () => {
  const audioRef = useRef(null)

  useEffect(() => {
    if (audioRef.current) {
      audioRef.current.play()
    }

    return () => {
      if (audioRef.current) {
        audioRef.current.pause()
      }
    }
  }, [audioRef])

  return (
    <div>
      <video ref={audioRef} src="audio.mp3" controls />
    </div>
  )
}

Here's Answer to Your Question

  1. By first calling the old ref callback with null, React provides you with an opportunity to perform any cleanup or teardown logic specific to the old DOM element. In the example above, before the new audio element is assigned to audioRef.current, the cleanup function inside useEffect is called, allowing us to pause the old audio element using audioRef.current.pause().

  2. React clears the old ref by calling the ref callback twice. The first call with null effectively clears the reference to the old DOM element, indicating that it's no longer being referenced by that particular ref (audioRef). This allows you to perform any necessary cleanup tasks or release any resources associated with the old DOM element. The second call with the new DOM element assigns the ref to the new DOM element (audioRef.current = newElement), allowing you to access and work with it.

Favata answered 22/5, 2023 at 21:59 Comment(0)
W
0

there is a simpler approach use state instead of Ref if you want the ref to change and on re-render not go to null. although it is something not recommended if you are using refs but it would solve the problem.

  const [refElement, setRefElement] = useState(null)
  return (
    <div
    ref={(el)=>setRefElement(el)}
    />
    )

Wiskind answered 25/5, 2023 at 16:14 Comment(0)
E
0

When React updates a component's rendered output, it may replace the old DOM element with a new one. To handle this change, React follows a two-step process when calling the ref callback.

First, React call the old ref callback with null. This allows us to perform any necessary cleanup operations associated with the previous DOM element. For example, we can remove event listeners, cancel timers or clean up any other resources that were set up for the old element. The null value indicates that the old element is being unmounted, and it gives us a chance to release any resources associated with it.

After the cleanup step, React calls the ref callback again, but this time with the new DOM element as an argument. Here, you can perform any additional setup or operations required for the updated element. We can store a reference to the new element or perform any other necessary tasks.

In short, React first calls the old ref callback with the null to allow for cleanup operations related to the previous DOM element. Then, it calls the new ref callback with the new DOM element to set up the reference to the updated element. This two-step process ensures that we have the opportunity to release resources and properly handle the transition between the old and new elements.

Endocrinotherapy answered 25/5, 2023 at 16:17 Comment(0)
H
0

React calls the old ref callback with null to allow you to have a chance to clean up any resources associated with the old DOM element. If you have event listeners or other references to the old DOM element, this provides an opportunity to release them before the new ref is set.

React clears the old ref by invoking the ref callback with null as the argument, ensuring that the old DOM reference is removed. By calling the ref callback twice, React ensures that old resources are cleaned up before setting the new ref. The first call sets the old ref to null, and the second call passes the new DOM element to the ref callback. This process allows you to manage the transition between old and new refs correctly.

Helman answered 26/5, 2023 at 10:33 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.