Lit-Elements external js file as storage changed by a property data binding

788 Views Asked by At

i try to use in lit-elements a external js file for init values but if i do so, it isnt changebel anymore via property binding. if i write it without the extanal storage file just use this. scope and declare it in the constructor, everything works fine. But as an external file not ... ?:/

but why?

i have two files menu.js:

import { LitElement, html } from '@polymer/lit-element';
import '@polymer/iron-pages/iron-pages.js';
import './main.js'
import { store } from './store'

class MenuElement extends LitElement {

  constructor() {
    super()
    this.page = 0;
    this.ninjas = ['Ninja1', 'Ninja2', 'Ninja3']
    this.log()
  }
  static get properties() {
    return {
      page: {
        type: Number
      },
      header: String,
      ninjas: Array,
      store: {
        type: Object,
        page: {
          type: Number
        }
      }
    }
  }

  render() {
    return html`
      <style>
        /* :host {
          border: solid 10px blue;
        } */
        ::slotted(h3) {
          border: solid 1px red
        }
      </style>
      <div>
        <ul>
          <li @click="${ (e) => { this.changePage2(e) } }">Home</li>
          <li @click="${ (e) => { this.changePage(e) } }">Page</li>
        </ul>
        <ul>
          ${this.ninjas.map(i => html`<li>${i}</li>`)}
        </ul>
      </div>

      <iron-pages selected="${ store.page }">
        <slot name="lala"></slot>
        <div><slot name="testSlot"></slot> Page 0</div>
        <main-view></main-view>
      </iron-pages>

    `;
  }

  changePage() {
    store.page = 1;
    console.log(store.page)
  }
  changePage2() {
    store.page = 0;
    console.log(store.page)
  }
  log() {
    console.log(store)
    console.log(store.page)
  }
}
customElements.define('app-menu', MenuElement);

and b store.js

export let store = {
  page: 1
}

thank You for any ideas =)

1

There are 1 best solutions below

0
On

To quote dracco

Actually it's not about JS, every objective language can have a collection structure, but modifying the collection does not modify the object. Comparing in JS means comparing references (it would be impossible to make a universal and fast content comparison), so pushing things to an array keeps the reference the same (as it is still the same instance of an Array class) - just the contents change. Similarly in class Person { constructor() { this.isBanned = false; } }, if you create a new instance (const p = new Person();) and then modify the property (p.isBanned = true;), it is still the same instance it was before, just the property differs.

You can read the full story at https://open-wc.org/faq/rerender.html

In the object reference for the external store never changes and therefore no render is triggered.

What you can do

Trigger it manually

with something like this

changePage() {
  store.page = 1;
  this.requestUpdate();
}

Use a state library

For example

they, of course, all come with their own set of rules and know how.