What causes a React Ref callback to be invoked multiple times during the initial loading of a page?

To find more information, please visit this URL within the React DOCS. You can also access a version of this code here.

I acknowledge that it is recommended to use the useCallback hook in a Functional React Component to create a ref callback according to the React Docs URL above. However, I wanted to explore what would occur if an ordinary arrow function (inline function) was used instead as a ref callback.

Thus, below is a modified version of the code from the mentioned URL without utilizing the useCallback hook. Instead, there's a simple arrow function serving as a ref callback. Additionally, two console.log statements have been added. The code snippet is available at 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);

Upon loading this app, the following sequence is displayed with numbering:

  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.

What causes the ref callback to be triggered three times and why does the component render thrice upon initial load?

Answer №1

What is the reason for the callback ref being called thrice and causing three initial renders of the component?

This behavior occurs because inside the callback ref, measuredRef(), a state update is triggered using setHeight().

Let's break it down step by step:

  1. Initial Render
  2. Setting height
    node =  <h1>Hello, world</h1>
    : Initial Render, Ref assignment
  3. Component Re-render: Triggered due to height update

The last two renderings are in line with the explanation provided about callback refs in the React documentation:

Callback ref defined as an inline function will be called twice during updates, first with null and then with the DOM element.

  1. Setting height. node = null: Null value after height update
  2. Setting height
    node =  <h1>Hello, world</h1>
    : DOM element available now

UPDATE (for the last render #6):

  1. The final render occurred because of #5 where node != null, leading to invocation of setHeight.

i.e #4 (node = null) doesn't trigger a re-render since height is only set if node != null.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

How can I use vanilla JavaScript to retrieve all elements within the body tag while excluding a specific div and its descendants?

My goal is to identify all elements within the body tag, except for one specific element with a class of "hidden" and its children. Here is the variable that stores all elements in the body: allTagsInBody = document.body.getElementsByTagName('*&apos ...

What steps can be taken to resolve the error message "t.onSubmit is not a function" that occurs upon form submission?

Upon submitting a form, it should trigger the onSubmit method function. However, an error is being returned instead: TypeError: "t.onSubmit is not a function". I've attempted to address this issue by researching similar problems and solutions provide ...

Storing input field values in JavaScript using the onchange event handler.Would you like a different revision

I am looking to calculate the area by multiplying width and height entered into input fields, and then display the result. Any guidance would be greatly appreciated. Thank you! Here is my current code. const width = document.querySelector("#width"); con ...

Executing JavaScript code within an AJAX request

Having a problem with an AJAX function that I need help solving: PAGE A represents the main page. PAGE X represents the content loaded via AJAX. RES A represents the results from PAGE A. RES B represents the new results loaded via AJAX. PAGE A initially ...

Customizing ExtJS 4.1: Mastering field overrides

Seeking guidance on applying a plugin to all fields(numberfield, textfield, datefield, etc.) within the ExtJS 4.1 library. Does anyone have suggestions on how to achieve this? I understand that all fields are derived from BaseField. I attempted the follow ...

Issue with Dynamic Image Path in Require Function: Unable to locate the relative module

I've been struggling with an error in VueJs require function for the past two days. I'm attempting to pass a prop to the Home component and then display the image. Home.vue <template> <BlogPost :post="welcomeScreen"/> <B ...

Troubleshooting History.push issue in a Typescript and React project

Currently, I'm tackling a project using React and TypeScript, but I've encountered a problem. Whenever I attempt to execute a history.push function, it throws an error that reads: Uncaught (in promise) TypeError: history.push is not a function. ...

React Component not displaying properly when used inside a map iteration

I am currently working on rendering multiple components using the .map method on an array with specific content. Although I can't find any errors in the console, the component is not appearing in the DOM as expected. I attempted to set subHeader to nu ...

Altering the backdrop upon hovering over an element

As a beginner in Javascript and Jquery, I am working on creating an interactive feature where hovering over one element changes the background image in another column. I have managed to write the function, but now I want to add an animation to the image tr ...

Leverage Pinia store in Vue helper functions

I have been working on my Vue.js application and I am looking to implement some helper functions that will utilize a Pinia store within the app. These functions need to be accessible by multiple components. Should I define these helper functions directly ...

Renew Firebase Token

Currently, my email and password authentication flow in web Firebase JavaScript involves generating a token that I then verify on my node.js backend using firebase-admin. To make things easier, I store this generated token in the browser's local/sessi ...

How does the onclick event trigger even without physically clicking the button?

I am struggling with creating a simple button using mui. My intention is to activate a function only when the button is clicked, but for some reason, as soon as I enter the webpage, it triggers an alert automatically. This behavior is puzzling to me and ...

The dimensions of GridStack items specified in pixels for both height and width

I am facing a challenge with my GridStack items, which each contain elements like graphs that need to be re-rendered when the size of the gridstack item (cell) changes. I am attempting to use the change event on GridStack to detect the modified items and t ...

What is the proper way to utilize document.getElementById() within a standalone js file?

As I dive into learning web development for the first time, I've decided to keep my scripts organized in separate files. However, I'm facing a challenge when trying to access elements from these external files. Below is a snippet of the JavaScri ...

What is the reason for the absence of the $.ajax function in the jQuery package designed for node.js?

Here is my code sample, which I would like to use for practicing with jQuery's ajax function. Note that I have already installed the jQuery package using npm install jquery: var $ = require('jquery'); var remoteValue = false; var doSometh ...

Node.js encountered an SFTP error stating "Error: connect: An existing SFTP connection is already defined."

Working within my node.js application, I have implemented ssh2-sftp-client to upload an image every 5 seconds. The initial upload functions correctly, but upon repeating the process, I encounter an error message: node .\upload.js uploaded screenshot ...

Only include unique objects in the array based on a common property

I am currently working with the following array: [ {name: "Mike", code: "ABC123"}, {name: "Sarah", code: "DEF456"}, {name: "John", code: "GHI789"}, {name: "Jane", code: "JKL01 ...

What is the correct way to integrate $.deferred with non-observable functions?

Imagine you have two functions filled with random code and the time they take to complete is unknown, depending on the user's system speed. In this scenario, using setTimeout to fire function2 only after function1 finishes is not practical. How can j ...

Encountering an issue such as receiving the 'Error eacces mkdir' message when trying to execute the 'npm install -g create-react-app' command

Encountered an error while trying to install reactjs on Ubuntu using the npm install -g create-react-app command. The error message is as follows. Can someone please assist me in resolving this issue? This is the error I am receiving: npm ERR! Error: EAC ...

A helpful guide on how to dynamically input database values into the href attribute of an 'a' tag

How do I successfully pass an ID to href in my code? When I try to return it via req.params, it keeps coming back as undefined. I need the ID from the URL in order to use the findOne method to access the data stored in the database. I've searched thr ...