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

Error when an island returns a <tr/> component. #1140

Closed
nicolo-ribaudo opened this issue Apr 29, 2023 · 3 comments · Fixed by preactjs/preact#4043
Closed

Error when an island returns a <tr/> component. #1140

nicolo-ribaudo opened this issue Apr 29, 2023 · 3 comments · Fixed by preactjs/preact#4043

Comments

@nicolo-ribaudo
Copy link
Contributor

nicolo-ribaudo commented Apr 29, 2023

I have a server-side rendered table that uses an island that returns a <tr />.

The island code can be as simple as

export default function NewTripForm() {
  return <tr />;
}

In the browser console, I get this error from Preact:

Improper nesting of table. Your <tr> should have a <thead/tbody/tfoot/table> parent.
  in tr
  in NewTripForm
@lucacasonato
Copy link
Member

The error is from preact/debug. I assume this happens because preact does not control the tree above the <tr> element, and as such is not aware that it is actually in a <table>.

cc @marvinhagemeister

@nicolo-ribaudo
Copy link
Contributor Author

nicolo-ribaudo commented Apr 29, 2023

Just silencing the error if the <tr> is the root of the Preact-controlled tree is not enough.

My island looks like this:

import { newTripFormVisible } from "@/utils/signals.ts";

const TripsListRow = () => (
  <tr>
    <td>Hello</td>
  </tr>
);

export default function NewTripForm() {
  if (!newTripFormVisible.value) {
    // Islands cannot return null.
    // TODO: Revisit when https://github.com/denoland/fresh/issues/502 is fixed.
    return <tr style="display:none" />;
  }

  // This doesn't work
  return <TripsListRow />;

  // This does
  return (
    <tr>
      <td>Hello</td>
    </tr>
  );
}

Where newTripFormVisible is a signal whose value is initially false and becomes true when clicking on a button.

If NewTripForm directly returns the <tr> I get the error above but the row still appears. However, if NewTripForm returns TripsListRow, I get this error:

Uncaught (in promise) DOMException: Node.insertBefore: Child to insert before is not a child of this node debug.js:42:7
    Preact 6
    setState trips:3980
    Preact 4
    handleClick NewTripButton.tsx:26
    B Preact

As a workaround, I'm using TripsListRow as if it was a function and not a component.

@marvinhagemeister
Copy link
Collaborator

@lucacasonato yeah the error is coming from preact/debug and it walks up the virtual tree and expects a <table> node to be somewhere there. I guess with islands being a separate subtree that assumption doesn't hold true anymore. It's something we've been thinking a lot about in the Preact team and is very likely to be something I'll be working on next.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants