GV

GeezerVison

The World Wide Web, restored to 800 pixels of glory.

Home|About|Gaming cabinet|Archives|How it works|Starter sites

On this site

  • Sign in
  • ActionsCI/CD and automation
  • CodespacesCloud development environments
  • All Features
  • Documentation
  • Training
  • Certifications
  • Build with Copilot
  • Customize Copilot
  • Integrations
  • Trending repos
  • GitHub Sponsors
  • Developer articles
  • Enterprises

This view

  • Original page
  • New address

GeezerVison is showing github.com — Issue when re-rendering empty · Issue #41 · WebReflection/uhtml

Issue when re-rendering empty #41

New issue
Copy link
New issue
Copy link
Closed
Closed
Issue when re-rendering empty#41
Copy link
Labels
wontfixThis will not be worked onThis will not be worked on

Description

@keul
keul
opened on Mar 18, 2021
Issue body actions

note: Maybe this is not an issue, probably a wrong usage of the API, but as this wasted few hours I think it worth discussing.

I've a hooked-element/uhtml (however only uhtml seems involved in the issue) project where a component was rendering a set of items.

this.html`
      <ul>
        ${items.map((item) =>
            checkSomething(item) ? html`<li>${item.something}</li>` : html``
        )}
      </ul>`
  );

Some items must not be displayed, based on external factors.

I started this by using a react-like approach, where inside an items.map I was returning "null" to "render nothing".
I noted that returning "null" or empty strings is the wrong way, so I tried html`` and it worked.

But the issue arise when there's a re-render. In this case I get an error:

Uncaught DOMException: Node.insertBefore: Child to insert before is not a child of this node

I suspect the issue is related to multiple empty block one near another.

Here a codesandbox example:
https://codesandbox.io/s/uhtml-empty-issue-c7otb?file=/src/index.js

  • first run at page load: everything is OK
  • after click on "run" again: you (can) get the error

Question: although I easily fixed this by filtering out elements I don't want to display I'm wondering if this is an issue, or maybe something to be better documented. In any case I'm curious about what's wrong with html``.

Thanks!

Activity

  1. WebReflection commented on Mar 18, 2021

    @WebReflection
    WebReflection
    on Mar 18, 2021
    Owner
    More actions

    I easily fixed this by filtering out elements I don't want to display

    It's not just that ... if you don't filter you render <li></li> for no reasons, and it doesn't matter if these are empty or not, these are DOM nodes.

    However, I am not sure I understand what is item.something ... if it's a string, fallback to "", if you want the LI, otherwise filter upfront, 'cause with less nodes, you'll have better performance, despite the double loop.

  2. keul commented on Mar 18, 2021

    @keul
    keul
    on Mar 18, 2021
    Author
    More actions

    It's not just that ... if you don't filter you render

  3. for no reasons, and it doesn't matter if these are empty or not, these are DOM nodes.

    Uhm… I don't think you get what I mean. I'm "just" returning html`` , no empty LI. (Also LI is just an example, I'm not even rendering a list in my real case).

    Sorry, forget the code above, probably It's just confusing. try to look at the codesandbox

  4. WebReflection commented on Mar 18, 2021

    @WebReflection
    WebReflection
    on Mar 18, 2021
    Owner
    More actions

    Also LI is just an example, I'm not even rendering a list in my real case

    I just commented the example you provided

    try to look at the codesandbox

    OK, but it's the same issue ... holes are for nodes, you are still creating empty nodes for no reason, because you should filter upfront:

            ${numbers.filter(n => n > 0.6).map((n, index) =>
              html`<li>${index} - ${n.toFixed(2)}</li>`
            )}

    Regardless if uhtml should, or should not, behave magically (which I don't like, in general), it's conceptually wrong to just render nothing.

    Filtering holed Arrays (that's what you have there, basically a [node, null, node]) means degrading performance for everyone, because when the hole is an Array, uhtml expects it to be homogeneous, otherwise it cannot diff null with anything else, as null is one reference.

    In few words, I don't think I am interested in slowing uhtml due sloppy, holed, arrays, but this is surely something I could put in the README/documentation.

    I hope this answers, even if it's not what you expected 👋

  5. WebReflection commented on Mar 18, 2021

    @WebReflection
    WebReflection
    on Mar 18, 2021
    Owner
    More actions

    P.S. by "holes" I mean template interpolations

  6. WebReflection commented on Mar 18, 2021

    @WebReflection
    WebReflection
    on Mar 18, 2021
    Owner
    More actions

    P.S.2 ... if you really want to use that pattern, you can always returns instead a comment node, as that is preserved

    thing ? html`<li>thing</li>` : html`<!---->`

    this doesn't throw 👍 (but I still strongly suggest filtering instead, it's more logical and clean)

  7. WebReflection
    closed this as completedon Mar 18, 2021
  8. WebReflection
    added
    wontfixThis will not be worked onThis will not be worked on
    on Mar 18, 2021
  9. WebReflection commented on Mar 18, 2021

    @WebReflection
    WebReflection
    on Mar 18, 2021
    Owner
    More actions

    P.S.3 the issue, if you'd like to know details, is that:

    html``

    that is emptyness ... so it cannot find any node to reproduce:

    • not a text node
    • nothing at all

    which is why comment work, it's used as placeholder to DOM diff next render.

    Since there is a trim involved, not even \n would do, or an empty space, because templates are trimmed due the way these are used most of the time:

    render(document.body, html`
      <div>hello</div>
    `);

    However, as I think it's developer's duty to pass meaningful data to render, instead of expecting automatic placeholders or pass null and expect nothing, the comment hacks clearly shows that the data is wrong, not the rendering engine, as it receives data that it shouldn't, so I hope this is actually a good thing, for cleaner layouts/DOM as result.

    I will check if there is an easy way to skip null while rendering though, but I won't support empty templates (or, if I do, I will convert these as null).

  10. WebReflection commented on Mar 18, 2021

    @WebReflection
    WebReflection
    on Mar 18, 2021
    Owner
    More actions

    P.S.4 (last one, I promise)

    I had a look at udomdiff and this null idea would go on the critical path for rendering and diffing, as I need to check that b value is not null in various places ... otherwise I need to filter per each Array in search of null values ... and that's also critical path.

    So, long story short, please don't pass data you are not supposed to render, and I'll explain this in the readme, after filing an issue.

    Reacted by Luca Fabbri
  11. keul commented on Mar 18, 2021

    @keul
    keul
    on Mar 18, 2021
    Author
    More actions

    …and I'll explain this in the readme, after filing an issue.

    This was my targeting opening the issue: I was pretty sure it was a wrong usage of the lib (.filter.map just works) but it was not easy to know why it is forbidden without even getting a console warning or something.

    Thanks for the long explanation the emptyness stuff, very appreciated 🙇

  12. WebReflection commented on Mar 18, 2021

    @WebReflection
    WebReflection
    on Mar 18, 2021
    Owner
    More actions

    trade offs for code size and performance:

    • I could put renders within a try/catch
    • I could inform users where they've done something wrong
    • I rather keep this project as tiny, and fast, as possible, 'cause it's one of its main strength

    👋

    Reacted by Marcelo Volmaro
  13. WebReflection commented on Mar 19, 2021

    @WebReflection
    WebReflection
    on Mar 19, 2021
    Owner
    More actions

    Added notes under About data purity within the README
    https://github.com/WebReflection/uhtml#api-documentation

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    wontfixThis will not be worked onThis will not be worked on

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions

      You are visitor 01402503 — GeezerVison does not store the pages you look up.
      Best viewed with Netscape Navigator 4.7 or Internet Explorer 6 at 800×600. No cookies required.