How can I get component state change in another component with litElement?

*爱你&永不变心* 提交于 2021-01-28 08:50:37

问题


I started a project based on LitElement There are many components nested in each other, Let us say we have this structure:

the root component is my-app

import { LitElement, html, customElement, query } from 'lit-element';
import './my-form';
import './my-view';
import { MyView } from './my-view';

@customElement('my-app')
export class MyApp extends LitElement {
  @query('my-view') private myView?: MyView;

  private handleCountChange(e: CustomEvent<{ count: number }>) {
    if (!this.myView) throw 'my-view not found!';
    this.myView.count = e.detail.count;
  }

  render() {
    return html`
      <my-form @countChanged=${this.handleCountChange}></my-form>
      <my-view></my-view>
    `;
  }
}

as you see we have two components: my-form

import { LitElement, html, customElement, property } from 'lit-element';

@customElement('my-form')
export class MyForm extends LitElement {
  @property({ type: Number }) count: any = 0;

  private updateCount(e: KeyboardEvent) {
    this.count = (<HTMLInputElement>e.target).value;
    this.dispatchEvent(
      new CustomEvent('countChanged', {
        composed: true,
        bubbles: true,
        cancelable: true,
        detail: { count: this.count }
      })
    );
  }

  render() {
    return html`
      <input value=${this.count} @input=${this.updateCount} type="text" />
    `;
  }
}

and my-view:

import { LitElement, html, customElement, property } from 'lit-element';

@customElement('my-view')
export class MyView extends LitElement {
  @property({ type: Number }) count: number = 0;

  render() {
    return html`
      <p>${this.count}</p>
    `;
  }
}

To get the property count changes from my-form into my-view I dispatched event listener then used it at my-app then at handleCountChange I'm assigning the count value to MyView which imported as a class in addition to import it as a componet.

Currently, this works, but I feel it is a long way especially when I have more nested components. I would like to know if there is a better for doing that. Is there something similar to Context API which exists at react.js I thought about using redux but somebody didn't recommend it with litElemnt. One of the ideas I'm thinking is to dispatch the event to document instead of the current component, but maybe this is a bad practice! What are your suggestions, please let me know?


回答1:


you have probably resolve this issue, but I can send you how I would deal with this.

You need to lift your state up to your my-app component. This state will be a single source of truth and deliver count value to my-form and my-view child components.

In my-app component, you can change handleCountChange to something like this (in case, if you define count as an attribute and let my-app to receive initial value from attributes):

 private handleCountChange(e: CustomEvent<{ count: number }>) {
   this.setAttribute('count', count); // If you set `count` as observed attribute, you will not need to call `requestUpdate` method
 }

or like this, if you define count as class property

 private handleCountChange(e: CustomEvent<{ count: number }>) {
   this.count = count;
   this.requestUpdate(); // force to call render method which is necessary in this case
 }

Note that, you will have to send count value also to the my-form component. It will work also without it, but if you will do it, you will lost single source of truth of your state and that can cause potencional unexpected behaviour.

If you will need to send an example, please let me know.



来源:https://stackoverflow.com/questions/56719000/how-can-i-get-component-state-change-in-another-component-with-litelement

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!