aboutsummaryrefslogtreecommitdiff
path: root/lib/src/lustre.ffi.mjs
diff options
context:
space:
mode:
Diffstat (limited to 'lib/src/lustre.ffi.mjs')
-rw-r--r--lib/src/lustre.ffi.mjs30
1 files changed, 16 insertions, 14 deletions
diff --git a/lib/src/lustre.ffi.mjs b/lib/src/lustre.ffi.mjs
index 29a60a9..f29e7ea 100644
--- a/lib/src/lustre.ffi.mjs
+++ b/lib/src/lustre.ffi.mjs
@@ -1,12 +1,12 @@
import {
AppAlreadyStarted,
AppNotYetStarted,
+ BadComponentName,
ComponentAlreadyRegistered,
ElementNotFound,
NotABrowser,
} from "./lustre.mjs";
import { from } from "./lustre/effect.mjs";
-import { map } from "./lustre/element.mjs";
import { morph } from "./runtime.ffi.mjs";
import { Ok, Error, isEqual } from "./gleam.mjs";
@@ -81,32 +81,32 @@ export class App {
this.#view = () => {};
}
- #render() {
- const node = this.#view(this.#state);
- const vdom = map(node, (msg) => this.dispatch(msg));
-
- this.#root = morph(this.#root, vdom);
- }
-
#tick() {
this.#flush();
- this.#didUpdate && this.#render();
- this.#didUpdate = false;
+
+ if (this.#didUpdate) {
+ const vdom = this.#view(this.#state);
+
+ this.#root = morph(this.#root, vdom, (msg) => this.dispatch(msg));
+ this.#didUpdate = false;
+ }
}
#flush(times = 0) {
+ if (!this.#root) return;
if (this.#queue.length) {
while (this.#queue.length) {
const [next, effects] = this.#update(this.#state, this.#queue.shift());
-
+ // If the user returned their model unchanged and not reconstructed then
+ // we don't need to trigger a re-render.
+ this.#didUpdate ||= this.#state !== next;
this.#state = next;
this.#effects = this.#effects.concat(effects[0].toArray());
}
- this.#didUpdate = true;
}
// Each update can produce effects which must now be executed.
- while (this.#effects[0])
+ while (this.#effects.length)
this.#effects.shift()(
(msg) => this.dispatch(msg),
(name, data) => this.emit(name, data)
@@ -146,6 +146,7 @@ export const setup_component = (
render,
on_attribute_change
) => {
+ if (!name.includes("-")) return new Error(new BadComponentName());
if (!is_browser()) return new Error(new NotABrowser());
if (customElements.get(name)) {
return new Error(new ComponentAlreadyRegistered());
@@ -206,7 +207,7 @@ export const setup_component = (
}
connectedCallback() {
- this.appendChild(this.#container.firstElementChild);
+ this.appendChild(this.#container.firstChild);
}
attributeChangedCallback(name, prev, next) {
@@ -220,6 +221,7 @@ export const setup_component = (
}
}
);
+
return new Ok(null);
};