Lit-element: Adding items to array does not trigger _render call

Created on 18 Jun 2018  路  9Comments  路  Source: Polymer/lit-element

Description


When changing array data the change is not recognized until _requestRender() is called

Live Demo

https://glitch.com/edit/#!/bold-cuticle

Steps to Reproduce

  1. create my-element
  2. create an array property
  3. use the array property in the _render function
  4. add items to the array in an event listener function

Expected Results

The _render function is called

Actual Results

Nothing happens

Browsers Affected

  • [x] Chrome
  • [x] Firefox
  • [ ?] Edge
  • [x] Safari 11
  • [? ] Safari 10
  • [ ?] IE 11

Versions

  • lit-element: v0.5.2
  • webcomponents: vX.X.X

Most helpful comment

This is the expected behavior. On Polymer they have this.push. On lit-element you can do:

this.colors = [...this.colors, 'green']

To override the complete array instead of mutating it.

All 9 comments

lit-element observes only properties defined in static get properties(). It does not provide any interface to observe mutation of an array or an object. Observing mutation is quite complex task and is out of scope of lit-element.

If you don't want to use _requestRender(), you can use immutable arrays and objects, like I did in this example.

UPD: sorry, wrong url. Fixed

This is the expected behavior. On Polymer they have this.push. On lit-element you can do:

this.colors = [...this.colors, 'green']

To override the complete array instead of mutating it.

ok thx :)

I currently have an array that receives updates from my db. After any updates, I manually call requestRender, which works fine...but would using the spread operator be more performant than calling requestRender? On a side not, it would be amazing if I could specifically tell lit-element (or the render method) what property or item changed from the array and only update that. Is that something that's currently possible? Thanks!

Out of the box, LitElement uses a strict equals check to see if a property has changed. This means it's ideally suited to immutable data patterns as noted above.

However, sometimes, you need more control over this, so LitElement 0.6 will be exposing a property-based invalidation function so you can decide exactly when and if setting a property should trigger an invalidation and rendering. For example, if a property is always an object that should only trigger rendering if a key property changes, you could do this:

static get properties() {
  foo: {shouldInvalidate: (value, oldValue) => value.key !== oldValue.key;}
}

To make any set to a mutating object/array typed property always trigger invalidation, you could do something like the following. Please note that for performance reasons you should use this pattern sparingly because it can sometimes can result in a large amount of unnecessary work.

static get properties() {
  foo: { shouldInvalidate: (value, oldValue) => true }
}

@sorvell I can't seem to find a documentation for shouldInvalidate. Where should I look or is this just missing from the README?

Update

I found it: shouldInvalidate became hasChanged: https://github.com/Polymer/lit-element/commit/2667920b075c3521eb346c9b20e2d319baa65f18

@TimPietrusky The API was going through active development at the time of the last post, you'll see the updated property name available in the README as hasChanged, and can be applied to your property as such:

static get properties() {
  foo: { hasChanged: (value, oldValue) => true }
}

From the README:

React to changes: LitElement reacts to changes in properties and attributes by asynchronously rendering, ensuring changes are batched. This reduces overhead and maintains consistent state.

Just to be clear, this line should probably be changed to:

React to property changes: LitElement ONLY reacts to changes in properties and attributes defined in static get properties(). It does this by asynchronously rendering, and ensuring changes are batched. This reduces overhead and maintains consistent state.

The capitalized ONLY is "only" so that it stands out, probably shouldn't be caps in the README.

@Westbrook, I see the Advanced update lifecycle note about hasChanged:

If the property's hasChanged(value, oldValue) returns false, the element does not update. If it returns true, requestUpdate() is called to schedule an update.

When would you use something like this?

Was this page helpful?
0 / 5 - 0 ratings