Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

10.18 regression: setState triggers DOMException: Node.insertBefore: Child to insert before is not a child of this node #4221

Closed
emersion opened this issue Nov 28, 2023 · 22 comments · Fixed by #4312
Labels
needs-more-info The issue doesn't contain enough information to be able to help

Comments

@emersion
Copy link

Describe the bug
Getting this error (and app gets completely stuck) with 10.19.2. Everything works fine after a downgrade to 10.18.2.

Uncaught (in promise) DOMException: Node.insertBefore: Child to insert before is not a child of this node
    Preact 20
    switchBuffer app.js:535
    handleBufferListClick app.js:1573
    items buffer-list.js:66
    handleClick buffer-list.js:8
    Preact 24
    handleMessage app.js:1028
    connect app.js:799
    handleMessage client.js:450
    reconnect client.js:178
    reconnect client.js:176
    Client client.js:153
    connect app.js:762
    handleMessage app.js:1124
    Preact 6
    handleMessage app.js:1110
    connect app.js:799
    handleMessage client.js:450
    reconnect client.js:178
    reconnect client.js:176
    Client client.js:153
    connect app.js:762
    handleConfig app.js:390
    App app.js:242
    promise callback*App app.js:241
    Preact 4
    <anonymous> main.js:4
constants.js:2:13
    Preact 5
    switchBuffer app.js:535
    handleBufferListClick app.js:1573
    items buffer-list.js:66
    handleClick buffer-list.js:8
    Preact 24
    handleMessage app.js:1028
    connect app.js:799
    handleMessage client.js:450
    reconnect client.js:178
    (Async: EventListener.handleEvent)
    reconnect client.js:176
    Client client.js:153
    connect app.js:762
    handleMessage app.js:1124
    M Preact
    some self-hosted:137
    M Preact
    some self-hosted:137
    Preact 4
    handleMessage app.js:1110
    connect app.js:799
    handleMessage client.js:450
    reconnect client.js:178
    (Async: EventListener.handleEvent)
    reconnect client.js:176
    Client client.js:153
    connect app.js:762
    handleConfig app.js:390
    App app.js:242
    (Async: promise callback)
    App app.js:241
    Preact 4
    <anonymous> main.js:4

To Reproduce
I don't have a minimal reproducer (yet). Run npm update in gamja and then switch between tabs quickly.

@emersion
Copy link
Author

Hm, actually, 10.18 still has that bug, although happens less often. Attempting to downgrade to v10.17.1 now.

@JoviDeCroock
Copy link
Member

A minimal reproduction would really be needed, we can't run a whole repo sorry 😅

@emersion
Copy link
Author

I haven't managed to come up with a minimal reproduction, but can confirm that the bug is gone with v10.17.1.

@marvinhagemeister marvinhagemeister added the needs-more-info The issue doesn't contain enough information to be able to help label Jan 10, 2024
@emersion
Copy link
Author

emersion commented Jan 10, 2024

Got a better stack trace, the exception is raised here:

parentDom.insertBefore(parentVNode._dom, oldDom || null);

@JoviDeCroock
Copy link
Member

JoviDeCroock commented Jan 10, 2024

Hmm then it would be one of the commits in 10.18.0 and my assumption is that it would be this one then https://github.com/preactjs/preact/pull/4125/files#diff-1135418bf513cf842acabfdcae5e8e4fb2ab335d4483216d1b39e15a3caf342eR106 but then again that got removed in the latest versions so we would really need a reproduction sorry...

@andrewiggins
Copy link
Member

Thanks for the bug report. I know getting a repro can be hard sometimes. Can you perhaps share any other information about your app? For example, what other libraries are you using? hook, compat, signals? Are you using Suspense, memo, forwardRef? From the stack trace it looks you are doing something with web sockets? Are you using any React/Preact libraries to integrate those into your app?

@emersion
Copy link
Author

The app is very "basic", as in it only uses Preact class-based components and nothing else. The htm package is used for constructing the DOM (no JSX). No other Preact-related libraries are used. No hooks, nor compat, nor signals, nor Suspense, not memo, not forwardRef. WebSockets are used directly without an intermediate library (but are not involved here).

The error comes from here, called from a click event handler: https://git.sr.ht/~emersion/gamja/tree/141fc3e07c69b1985719d6075e2f101a3f73d6fe/item/components/app.js#L535

The error doesn't happen consistently, have to click multiple times to trigger it.

@developit
Copy link
Member

given that it's affected by timing, I wonder if this could be related to the event handler pathing fixes that went out in .19? There's a large VDOM tree here with an event handler defined at the root that should be a stable reference.

@emersion emersion changed the title 10.19 regression: setState triggers DOMException: Node.insertBefore: Child to insert before is not a child of this node 10.18 regression: setState triggers DOMException: Node.insertBefore: Child to insert before is not a child of this node Jan 10, 2024
@JoviDeCroock
Copy link
Member

JoviDeCroock commented Jan 11, 2024

That did go out in the same release, I am however confused how that would affect setting _nextDom, this does sound in the boathouse of #4161 when saying "rapid clicking"

@JoviDeCroock
Copy link
Member

JoviDeCroock commented Feb 16, 2024

Mind checking whether 10.19.6 fixes your issue?

@emersion
Copy link
Author

Yes, still seeing that bug in this release.

@emersion
Copy link
Author

I've tried https://github.com/nbalatsk-oracle/preact but could also reproduce this bug with that fork.

@JoviDeCroock
Copy link
Member

@emersion it would help us a lot to have this bug in a codesandbox or stackblitz

@objerke
Copy link

objerke commented Mar 19, 2024

@JoviDeCroock I've managed to reproduce the issue in a Stackblitz environment, using preact 10.19.7.

The issue can be seen if a keyed list item is moved to an earlier position, but also rendered as null. Here is the full example.

import { render } from 'preact';
import { useState } from 'preact/hooks';

const firstList: Item[] = [
  { id: 'One' },
  { id: 'Two' },
  { id: 'Three' },
  { id: 'Four' },
];

const secondList: Item[] = [
  { id: 'One' },
  { id: 'Four', renderAsNullInComponent: true },
  { id: 'Six' },
  { id: 'Seven' },
];

render(<App />, document.body);

export function App() {
  let [list, setList] = useState(firstList);

  return (
    <>
      <p>
        This is reproduction of{' '}
        <a href="https://github.com/preactjs/preact/issues/4221">
          Preact Issue 4221
        </a>
        . The list diffing breaks when clicking the button.{' '}
      </p>
      <div>
        {list.map((item) => (
          <RenderedItem key={item.id} item={item} />
        ))}
      </div>
      <button
        onClick={() => {
          setList(secondList);
        }}
      >
        Switch list
      </button>
    </>
  );
}

@JoviDeCroock
Copy link
Member

Thank you so much for the reproduction, mind checking out #4312 to see if it addresses your case in your bigger applications?

@emersion
Copy link
Author

emersion commented Mar 20, 2024

Many thanks to @objerke and @JoviDeCroock!

Unfortunately, I can still see the regression on 10.20.0…

@JoviDeCroock
Copy link
Member

JoviDeCroock commented Mar 20, 2024

@emersion with a minimal reproduction I can def look at it

EDIT: maybe related to #4194

@StabbarN
Copy link

StabbarN commented Apr 8, 2024

We can see it in 10.20.1.

@marvinhagemeister
Copy link
Member

@StabbarN can you share a reproduction case? We've addressed all the cases we were able to reproduce, but it looks like something eluded us.

@JoviDeCroock
Copy link
Member

JoviDeCroock commented Apr 8, 2024

This should be fixed by #4318 but a reproduction would be really welcome in this one. This however isn't released yet.

Edit: released in 10.20.2

@StabbarN
Copy link

StabbarN commented Apr 10, 2024

I was going to reproduce in a smaller repo but then I saw 10.20.2. I can reproduce it in 10.20.1 but not in 10.20.2 so this issue can most likely be closed.

Thanks!

@emersion
Copy link
Author

Yes, can confirm this is now fixed with 10.20.2. Cheers!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
needs-more-info The issue doesn't contain enough information to be able to help
Projects
None yet
Development

Successfully merging a pull request may close this issue.

7 participants