6

请参考React DOCS 中的这个URL。此代码的一个版本也可在此处获得。

我知道在 a 内部Functional React Component,最好使用useCallback钩子来创建 ref 回调,如上面的 React Docs URL 所示,但我想了解如果使用简单的arrow function(内联函数)作为 ref会发生什么打回来。

因此,在下面,我修改了上面 URL 中的代码以不使用useCallback钩子。相反,我只是使用常规arrow function作为 ref 回调。此外,我添加了两个 console.log 语句。这是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 次?

4

2 回答 2

8

为什么 ref 回调被调用了 3 次,为什么组件在初始加载时会渲染 3 次?

主要是因为在您的回调 ref,measuredRef()中,您正在通过setHeight().

这是一步一步的解释:

  1. 渲染:初始渲染
  2. 设置高度 node = <h1>Hello, world</h1>:初始渲染,参考分配
  3. 渲染。: 组件由于设置高度而重新渲染

对于最后两个打印,请参阅回调 refs 的警告

如果 ref 回调被定义为内联函数,它将在更新期间被调用两次,首先是 null,然后是 DOM 元素。

  1. 设定高度。node = null : null 由于高度更新
  2. 设定高度。 node = <h1>Hello, world</h1>: 现在有了 DOM 元素

更新(最后一次渲染#6)

  1. 最后一次渲染是由于 #5 where node != null. 就这样setHeight叫了。

#4 ( node = null) 不会导致重新渲染,因为只有在node != null.

于 2019-09-27T01:37:49.277 回答
1

请参阅带有 ref 回调的警告:https ://reactjs.org/docs/refs-and-the-dom.html#caveats-with-callback-refs

没有,每次渲染都会创建 useCallback一个新的函数回调函数。measuredRef

于 2019-09-28T10:31:49.920 回答