为啥在初始页面加载时多次调用 React Ref 回调(作为箭头函数或内联函数)?
Posted
技术标签:
【中文标题】为啥在初始页面加载时多次调用 React Ref 回调(作为箭头函数或内联函数)?【英文标题】:Why is a React Ref callback (as an arrow function or inline function) called multiple times on initial page load?为什么在初始页面加载时多次调用 React Ref 回调(作为箭头函数或内联函数)? 【发布时间】:2020-01-27 07:25:56 【问题描述】:请参考 React DOCS 中的this URL。此代码的一个版本也可在here 获得。
我知道在 Functional React Component
中,最好使用 useCallback
挂钩来创建一个 ref 回调,如上面的 React Docs URL 所示,但我想了解如果使用简单的arrow function
(内联函数)用作 ref 回调。
所以,下面,我修改了上面 URL 中的代码,不使用 useCallback
钩子。相反,我只是使用常规的arrow function
作为 ref 回调。此外,我添加了两个 console.log 语句。这是代码,也可以在this URL 获得。
import React, useState from "react";
import ReactDOM from "react-dom";
import "./styles.css";
function App()
const [height, setHeight] = useState(0);
const measuredRef = node =>
console.log("Setting height. node = ", node);
if (node !== null)
setHeight(node.getBoundingClientRect().height);
;
console.log("Rendering.");
return (
<div className="App">
<h1 ref=measuredRef>Hello, world</h1>
<h2>The above header is Math.round(height)px tall</h2>
</div>
);
const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);
加载此应用时,会打印以下内容(添加编号):
1. Rendering.
2. Setting height. node = <h1>Hello, world</h1>
3. Rendering.
4. Setting height. node = null
5. Setting height. node = <h1>Hello, world</h1>
6. Rendering.
为什么 ref 回调被调用了 3 次,为什么组件在初始加载时会渲染 3 次?
【问题讨论】:
【参考方案1】:为什么 ref 回调被调用了 3 次,为什么组件在初始加载时会渲染 3 次?
主要是因为在您的回调引用 measuredRef()
中,您正在通过 setHeight()
进行状态更新。
这里是一步一步的解释:
-
渲染:初始渲染
设置高度
node = <h1>Hello, world</h1>
:初始渲染,参考分配
渲染。:组件因设置高度而重新渲染
最后两张打印,参考caveats of callback refs:
如果 ref 回调被定义为内联函数,它将在更新期间被调用两次,第一次使用 null,然后再次使用 DOM 元素。
-
设置高度。 node = null:由于高度更新为null
设置高度。
node = <h1>Hello, world</h1>
: 现在使用 DOM 元素
更新(最后一次渲染 #6):
-
最后一次渲染是由于 #5 其中
node != null
。所以setHeight
被调用了。
即#4 (node = null
) 不会导致重新渲染,因为只有在node != null
时才设置高度。
【讨论】:
【参考方案2】:查看 ref 回调的注意事项:https://reactjs.org/docs/refs-and-the-dom.html#caveats-with-callback-refs
没有useCallback
,每次渲染都会创建一个新的回调函数measuredRef
。
【讨论】:
以上是关于为啥在初始页面加载时多次调用 React Ref 回调(作为箭头函数或内联函数)?的主要内容,如果未能解决你的问题,请参考以下文章
在页面加载期间多次调用 React onChange 处理程序