brianyates
brianyates

Reputation: 399

Is there a need to do any cleanup when using document.createElement within a React ref?

Per the title, if I were to do something like the code snippet below, since React.useRef will get called on every render, is there any need to do cleanup on the call to document.createElement("div"), or will the browser garbage collect that div that gets created when the next render comes?

I'm aware that if I were to actually append the div with document.body.appendChild then I'd need to clean up the element that actually gets appended...I'm just wondering about the div that's stored in memory after React.useRef is called.

function Modal() {
  const portalRef = React.useRef(document.createElement("div"));
  return null;
}

Upvotes: 0

Views: 392

Answers (1)

kca
kca

Reputation: 6073

The DIV doesn't need to be cleaned up manually, but also the creation of the DIV doesn't relate to the fact that useRef is beeing called on every render, i.e. the DIV itself is created on every render, independently of useRef.

Consider this way of refactoring your code:

function Modal() {
  const newDiv = document.createElement("div"); // <-- new DIV created
  const portalRef = React.useRef( newDiv );     // <-- useRef called
  return null;
}

Here it becomes obvious how just a plain old DOM object (the new DIV) is created on every render. Normal Javascript / DOM behavior applies regarding the DIV.

useRef only uses the first created DIV as an initial value, and just ignores all following ones.

Indeed, this is a wasted creation of a DIV on every render. The best solution to this depends on the purpose of the code. E.g.:

  • you should not use document.createElement("div") anyway,
  • useRef would better only contain primitive values, instead of objects, and the DIV should be created by React mechanisms,
  • when you need a constant, "expensive" initial value, you might create it only once, before the component is even mounted, outside of the component
  • ... etc.

Furthermore, the value contained inside the useRef is also just a plain Javascript object (basically), and will behave as such.

I.e. portalRef is just an object { current: myInitialDiv }, which lives as long as the component does, and gets deleted then. Note that this myInitialDiv is still the first DIV that was created, not one of the later ones.

Upvotes: 1

Related Questions