lit: Render method doesn't work as spected

Description

render method not overwritting the existing HTML

Steps to Reproduce

  1. Write this code
import {html, render} from 'lit-html';

const handleClick = () => {
let content = document.getElementById('content')
render(html`New Content`, content)
}

render(html`
<div >
<button @click={handleClick}>Click me!</button>
<div id="content">
Old Content
</div>
</div>`, document.body);

Expected Results

On click, doesn’t overwrite the content.

<div >
<button @click={handleClick}>Click me!</button>
<div id="content">
New Content
</div>
</div>

Actual Results

<div >
<button @click={handleClick}>Click me!</button>
<div id="content">
Old Content
New Content
</div>
</div>

About this issue

  • Original URL
  • State: closed
  • Created 3 years ago
  • Comments: 16 (3 by maintainers)

Most upvoted comments

Thank you for your comment, although it is not what I was looking for, it has helped me to better understand the problem.

According to my idea, I think there should be an option such as:

render(html``, root, {append:false})

@justinfagnani we can’t really do it based on https://github.com/lit/lit/blob/main/packages/lit-html/src/lit-html.ts#L1145

this breaking change makes our website not working anymore

the problem is we can only clean it once with innerHTML, otherwise, we constantly get the error.

I think whether we add option to replace the node, or we stop throwing error if this.parentNode is not found, and treat it as a new node

render() appends to the container. This is a change from lit-html 1.x. If you want to old container-clearing behavior you’ll need to clear it yourself:

You can either do it eagerly:

import {html, render} from 'lit-html';

const handleClick = () => {
  let content = document.getElementById('content');
  render(html`New Content`, content);
}

render(html`
  <div >
    <button @click={handleClick}>Click me!</button>
    <div id="content">
      Old Content
    </div>
  </div>`, document.body);

// clear the container:
let content = document.getElementById('content');
content.innerHTML = '';

Or on-demand by keeping some state:

import {html, render} from 'lit-html';

let containerCleared = false;
const handleClick = () => {
  let content = document.getElementById('content');
  if (!containerCleared) {
    containerCleared = true;
    content.innerHTML = '';
  }
  render(html`New Content`, content);
}

render(html`
  <div >
    <button @click={handleClick}>Click me!</button>
    <div id="content">
      Old Content
    </div>
  </div>`, document.body);

We’re not inclined to add or change behavior here, which is documented in the upgrade guide (https://lit.dev/docs/releases/upgrade/#lit-html). I think our suggestion would be to create a helper around render to perform the behavior you want.