React如何在重新渲染后调用ref回调时清除旧ref



React文档中提到:

如果ref回调被定义为内联函数,那么在更新期间它将被调用两次,第一次使用null,然后再次使用DOM元素。这是因为每次渲染都会创建一个新的函数实例,因此React需要清除旧的ref并设置新的ref。

我可以理解el被设置为null,因为我们需要在重新渲染后释放旧dom节点的内存。但是,有两个问题我还是想不通。

  1. 为什么React必须首先用null调用旧的ref回调?难道它不能用新的dom节点调用更新的ref回调吗
  2. React如何清除旧裁判?这与两次调用ref回调有关吗

您可以ref重置为回调ref作为一种效果。事实并非如此,但我认为对问题的重新描述确实有助于理解。

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

假设您将ref回调传递给DOM节点:

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

根据效果进行思考:

  1. 当组件挂载时,它会使用该元素调用ref回调
  2. 当组件卸载时,它用null调用ref回调,因为这是";清除">
  3. 当组件改变时;清除";然后它建立新的";效果">

再一次,这是说它正在使用一个真正的useEffect,但它背后的想法是一样的。

React调用ref回调时,需要知道是在设置新的ref还是删除旧的ref
通过用null参数调用旧的ref回调,React向回调发出信号,表示应该清除对前一个元素的引用

示例代码:-

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>
)
}

以下是您问题的答案

  1. 通过首先用null调用旧的ref回调,React为您提供了执行任何特定于旧DOM元素的清理或拆卸逻辑的机会。在上面的例子中,在将新的音频元素分配给audioRef.current之前,会调用useEffect内部的清理函数,允许我们使用audioRef.courrent.pause().暂停旧的音频元素

  2. React通过两次调用ref回调来清除旧的ref。使用null的第一个调用有效地清除了对旧DOM元素的引用,表明该元素不再被特定的ref(audioRef)引用。这允许您执行任何必要的清理任务或释放与旧DOM元素相关联的任何资源。使用新DOM元素的第二个调用将ref分配给新DOM元素(audioRef.current=newElement),允许您访问和使用它

如果您希望Ref更改并且在重新渲染时不为null,则有一种更简单的方法使用state而不是Ref。尽管如果你使用refs,这是不推荐的,但它可以解决问题。

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

React更新组件的渲染输出时,可能会用新的DOM元素替换旧的DOM元素。为了处理这一变化,React在调用ref回调时遵循两步过程。

首先,React用null调用旧的ref回调。这允许我们执行与前一个DOM元素相关联的任何必要的清理操作。例如,我们可以删除事件侦听器、取消计时器或清除为旧元素设置的任何其他资源。空值表示旧元素正在被卸载,这给了我们释放与它相关联的任何资源的机会

在清理步骤之后,React再次调用ref回调,但这次使用新的DOM元素作为参数。在这里,您可以执行更新元素所需的任何其他设置或操作。我们可以存储对新元素的引用或执行任何其他必要的任务。

简而言之,React首先用null调用旧的ref回调,以便进行与前一个DOM元素相关的清理操作。然后,它使用新的DOM元素调用新的ref回调,以设置对更新元素的引用。这个分两步走的过程确保我们有机会释放资源,并正确处理新旧元素之间的转换。

React使用null调用旧的ref回调,使您有机会清理与旧DOM元素相关的任何资源。如果您有对旧DOM元素的事件侦听器或其他引用,这就提供了在设置新引用之前释放它们的机会。

React通过调用以null为参数的ref回调来清除旧的ref,确保删除旧的DOM引用。通过两次调用ref回调,React确保在设置新的ref之前清理掉旧的资源。第一次调用将旧的ref设置为null,第二次调用将新的DOM元素传递给ref回调。这个过程允许您正确地管理新旧裁判之间的转换。

最新更新