• Introduction
    • Why Liquid Oxygen
    • Getting started
      • React
      • Vue
  • Guides
    • CSS vs. Web Components
    • Component assets
    • Type checking and intellisense
    • Server-side rendering
    • Event handling
    • Form validation
    • Tailwind CSS integration
    • Design tokens
    • Testing
    • Sandbox applications
    • Troubleshooting
      • Popped-out element is rendered in wrong container
      • Failed to execute removeChild on Node
    • FAQ
    • Contributing
  • Globals
    • Animations
    • Border-radius
    • Colors
    • Focus
    • Fonts
    • Shadows
    • Spacings
    • Theming
    • Typography
  • Components
    • Accordion
      • Accordion Panel
      • Accordion Section
      • Accordion Toggle
    • Background Cells
    • Badge
    • Breadcrumbs
      • Crumb
    • Button
    • Card
      • Card Stack
    • Checkbox
    • Circular Progress
    • Context Menu
      • Menu
      • Menuitem
      • Menuitem Group
    • Cookie Consent
    • Header
    • Icon
    • Input
    • Input Message
    • Label
    • Link
    • Loading Indicator
    • Modal
    • Notice
    • Notification
    • Pagination
    • Progress
    • Radio Button
    • Screen Reader Live
    • Screen Reader Only
    • Select
      • Option
      • Option Group
    • Sidenav
      • Sidenav Accordion
      • Sidenav Back
      • Sidenav Header
      • Sidenav Heading
      • Sidenav Navitem
      • Sidenav Separator
      • Sidenav Slider
      • Sidenav Subnav
      • Sidenav Toggle Outside
    • Slider
    • Stepper
      • Step
    • Switch
      • Switch Item
    • Table
      • Table Body
      • Table Caption
      • Table Cell
      • Table Colgroup
      • Table Column
      • Table Footer
      • Table Head
      • Table Header
      • Table Row
      • Table Toolbar
    • Tabs
      • Tab
      • Tab List
      • Tab Panel
      • Tab Panel List
    • Toggle
    • Tooltip
    • Typography
  • Data Visualization
    • Getting Started
  1. Problem
  2. Solution
Guides Troubleshooting Failed to execute removeChild on Node
(external link)

Failed to execute removeChild on Node #

Problem #

Some components have a popper element which displays the slotted elements in a portal (a different place in the DOM). The ld-context-menu component and the ld-tooltip component are examples of such components. In order to keep all event listeners attached and working, the components move the original element including all the attached event listeners to the popper element.

In some cases this behavior can be problematic. For instance: If you are using a UI library which renders elements based on state (such as React or Vue) and have a conditionally rendered element as a direct child of a component that moves the Node to a different place in the DOM, you may run into the error:

Uncaught DOMException: Failed to execute 'removeChild' on 'Node': The node to be removed is not a child of this node.

Solution #

The current workaround is to wrap the conditionally rendered element in another element.

Does not work:

export default function App() {
  const tetherOptions = {
    bodyElement: document.getElementById('root')
  }
  const [checked, setChecked] = useState(true)
  return (
    <>
      <LdButton onClick={() => { setChecked(!checked) }}>Toggle checked</LdButton>
      <LdTooltip arrow tetherOptions={tetherOptions as any} triggerType="click">
        {checked && <span>🤓</span>}
      </LdTooltip>
    </>
  );
}

Works:

export default function App() {
  const tetherOptions = {
    bodyElement: document.getElementById('root')
  }
  const [checked, setChecked] = useState(true)
  return (
    <>
      <LdButton onClick={() => { setChecked(!checked) }}>Toggle checked</LdButton>
      <LdTooltip arrow tetherOptions={tetherOptions as any} triggerType="click">
        <div>
          {checked && <span>🤓</span>}
        </div>
      </LdTooltip>
    </>
  );
}