Skip to content

Instantly share code, notes, and snippets.

@jmonster
Last active September 30, 2024 15:08
Show Gist options
  • Save jmonster/fc07b7abd4ac477a4563bb7bd7f60158 to your computer and use it in GitHub Desktop.
Save jmonster/fc07b7abd4ac477a4563bb7bd7f60158 to your computer and use it in GitHub Desktop.
🔥 TLit;DR

Main Points:

  1. @property - shouldRun:

    • This is a public reactive property that can be passed in as an attribute from outside the component (e.g., <my-timer should-run></my-timer>).
    • When it toggles, based on whether it's true or false, it controls whether the timer increments.
  2. @state - _count:

    • This is an internal reactive state that holds the number of intervals passed (the count). It is not exposed outside the component and is intended for internal component reactivity.

Lifecycle Hooks:

  • constructor:
    • Called first, used to bind functions or initialize non-reactive properties.
  • connectedCallback:
    • Runs when the component is added to the DOM. Used here to start the interval based on an initial value of shouldRun.
  • disconnectedCallback:
    • Runs when the component is removed from the DOM. Used to clean up by clearing the interval.
  • firstUpdated:
    • Runs after the first render. You can do any additional logic after the initial DOM structure is created.
  • willUpdate:
    • Runs before each reactive update. Logs the changes for demonstration purposes.
  • updated:
    • Runs after properties or state have changed and the component re-renders. Used here to handle logic when shouldRun changes.

Behavior:

  • When <my-timer> gets the property should-run, it starts incrementing the _count.
  • When should-run is omitted, the interval stops, and the count freezes.
See the following well-written docs for more information
- https://lit.dev/docs/components/overview/
- https://lit.dev/docs/templates/overview/
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>My Timer Example</title>
<script type="module" src="my-timer.js"></script> <!-- Assuming your component is in 'my-timer.js' -->
</head>
<body>
<!-- Starts the interval and updates the count because should-run is true -->
<my-timer should-run></my-timer>
<!-- Component with should-run initially false, interval won't start -->
<my-timer></my-timer>
</body>
</html>
import { LitElement, html, css, nothing } from 'lit';
import { customElement, property, state } from 'lit/decorators.js';
@customElement('my-timer')
class MyTimer extends LitElement {
// A public property that can be set from outside the component
@property({ attribute: 'should-run', type: Boolean })
shouldRun = false; // Determines if the timer should run
// Internal state to hold the current count
@state()
private _count = 0;
// Hold a reference to the interval, so we can clear it later
private _intervalId = null;
static styles = css`
div {
font-size: 20px;
font-family: Arial, sans-serif;
color: #333;
margin-bottom: 10px;
}
button {
padding: 8px 12px;
font-size: 16px;
cursor: pointer;
}
`;
constructor() {
super();
this._increment = this._increment.bind(this);
this._toggleRun = this._toggleRun.bind(this); // Bind the toggle function
}
connectedCallback() {
super.connectedCallback();
if (this.shouldRun) {
this._startInterval();
}
}
disconnectedCallback() {
super.disconnectedCallback();
this._clearInterval();
}
firstUpdated() {
console.log('Component rendered for the first time!');
}
willUpdate(changedProps) {
console.log('Component will update, changed properties:', changedProps);
}
updated(changedProps) {
if (changedProps.has('shouldRun')) {
this._handleRunState();
}
}
_handleRunState() {
if (this.shouldRun) {
this._startInterval();
} else {
this._clearInterval();
}
}
_startInterval() {
this._intervalId = setInterval(this._increment, 1000);
}
_clearInterval() {
if (this._intervalId) {
clearInterval(this._intervalId);
this._intervalId = null;
}
}
_increment() {
this._count += 1;
}
// Toggles the shouldRun property when the button is clicked
_toggleRun() {
this.shouldRun = !this.shouldRun;
}
render() {
return html`
<div>
Count: ${this._count}
</div>
<button @click="${this._toggleRun}">
${this.shouldRun ? 'Stop' : 'Start'} Timer
</button>
`;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment