[feat]: slotController synchronous `hostUpdated()`
Nessuno ha ancora preso questa issue.
Valutazione
- Difficoltà
- 4/5
- Tempo stimato
- 3-5 giorni
- Idoneità per principianti
- 55/100
- Tipo di issue
- Funzionalità
- Chiarezza
- Abbastanza chiara
- Stato di attività
- Tranquilla
- Stack tecnologico
- typescript
- Ambito
- frontend
Direzione di ricerca
Start by locating the slotController implementation and the SlotControllerPublicAPI declaration, then trace hostConnected, #initSlotMap, the MutationObserver, and the hasSlotted(), isEmpty(), and getSlotted() methods. Implement the synchronous lifecycle described in the issue and verify initial connection, reconnection, and child mutations produce correct slot state without an async timing gap.
Scritto dal modello di indicizzazione a partire dal testo della issue.
Descrizione
Alternative approach:
synchronous hostUpdated() instead of async fallback
The current fix adds a fallback in getSlotted() to query slot elements directly when #slotRecords hasn't been populated yet. This addresses the symptom but leaves the root cause: hostConnected and #initSlotMap are async, creating a timing gap where no data source exists.
The gap also affects hasSlotted() and isEmpty(), which aren't addressed here.
Why hostConnected is async
Both hostConnected and #initSlotMap await host.updateComplete just to ensure the shadow DOM exists so they can query for elements. But Lit already provides a synchronous hook that guarantees this: hostUpdated(), which runs after every render when the DOM has been committed.
Suggested change
Make hostConnected synchronous (just sets up the MutationObserver), move record initialization to hostUpdated(), and have the MutationObserver trigger a re-render instead of calling #initSlotMap directly:
hostConnected(): void {
this.#mo.observe(this.host, { childList: true });
this.#slotRecords.clear();
}
hostUpdated(): void {
if (this.#slotRecords.size === 0) {
for (let slotName of this.#slotNames.concat(Object.values(this.#deprecations))) {
slotName ||= SlotController.default;
const slot = this.#getSlotElement(slotName);
if (slot) {
this.#slotRecords.set(slotName, new SlotRecord(slot, slotName, this.host));
}
}
if (this.#slotRecords.size > 0) {
this.host.requestUpdate();
}
}
}
The MutationObserver callback becomes:
#mo = new MutationObserver(() => this.host.requestUpdate());
And #initSlotMap can be removed entirely.
This also requires updating the SlotControllerPublicAPI declaration to match:
hostConnected?(): void;
Why this works
- First render: Records empty,
isEmpty()returns true (matches SSR server behavior).hostUpdated()populates records and calls requestUpdate(). - Second render: Records exist,
isEmpty()/getSlotted()read live DOM via SlotRecord getters, correct results.hostUpdated()sees records exist, norequestUpdate(), no infinite loop. - MutationObserver: Child changes trigger
requestUpdate()→ re-render → SlotRecord getters reflect new DOM state. No record rebuild needed since they query live DOM. - Reconnection:
hostConnectedclears records → next render →hostUpdated()repopulates.
What this fixes that the current PR doesn't
hasSlotted()andisEmpty()have the same timing gap, they also read from #slotRecords and return incorrect results before async init completes. ThehostUpdated()approach fixes all three methods.- Eliminates the
asyncarchitecture that caused the issue rather than working around it.
Trade-off
The two-render pattern on initial connection is inherent <slot> elements are created by render(), so the first render can't know about them. This was already the case with the async approach.
We can spin this off to another issue if we feel the need
Originally posted by @zeroedin in https://github.com/patternfly/patternfly-elements/issues/3093#issuecomment-4252752632
- Lingua principale
- TypeScript
- Stelle
- 394
- Fork
- 107
- Metriche di merge delle PR
- Nessuna PR unita negli ultimi 30g
Guida per i contributori
Apri la guida per i contributori
Come iniziare
- Leggi tutta la issue e poi la guida ai contributi del progetto.
- Commenta sulla issue per dire che te ne occupi tu — evita che due persone facciano lo stesso lavoro.
- Fai un fork del repository e lavora su un branch.
- Apri una pull request che faccia riferimento al numero della issue.
Altre issue di patternfly/patternfly-elements
-
bug
patternfly/patternfly-elements#3158 · 1 assegnatario ·
-
patternfly/patternfly-elements#3136 · 1 commento · 1 assegnatario ·
-
docs
patternfly/patternfly-elements#3131 · 1 assegnatario ·
-
Difficoltà 4/5 3-5 giorni Idoneità per principianti 55/100
patternfly/patternfly-elements#3122 ·
-
Difficoltà 5/5 Più di una settimana Idoneità per principianti 38/100
patternfly/patternfly-elements#3118 ·
Tutte le issue di patternfly/patternfly-elements
Issue simili
-
Difficoltà 2/5 1-3 ore Idoneità per principianti 65/100
-
Difficoltà 2/5 1-3 ore Idoneità per principianti 75/100
-
bug v2
Difficoltà 2/5 1-3 ore Idoneità per principianti 75/100
modelcontextprotocol/inspector#2458 · 1 commento ·
-
Difficoltà 1/5 Meno di un'ora Idoneità per principianti 75/100
railmapgen/rmp-gallery#4068 ·
-
Mend: dependency security vulnerability status: needs triage 🕵️♀️
Difficoltà 2/5 1-3 ore Idoneità per principianti 70/100
carbon-design-system/ibm-products#9907 ·