Anchor-click and form-submit navigations run outside the runtime's interaction frame (observe: NavigationEvent.interaction is undefined)
Maintainer antworten meist innerhalb von 1 Tag
Dieses Issue hat noch niemand übernommen.
Bewertung
- Schwierigkeit
- 4/5
- Geschätzter Aufwand
- 3-5 Tage
- Anfängerfreundlichkeit
- 52/100
- Issue-Typ
- Bug
- Klarheit
- Größtenteils klar
- Aktivitätsstatus
- Aktiv
- Tech-Stack
- typescript
Rechercherichtung
Start in src/data/events.ts at setupNativeEvents, then inspect @solidjs/web's internal addEvent and the delegated event path through delegateEvents. Preserve the existing listener order and preload behavior; done means anchor clicks and native form submissions receive interaction attribution, preventDefault still works, and non-observe builds remain unchanged.
Vom Indexierungsmodell aus dem Issue-Text verfasst.
Beschreibung
Summary
Under Solid's observe tier, a navigation performed by clicking an <a> records no interaction: NavigationEvent.interaction is undefined, and the calls the route's data makes carry a navigation origin with no click behind it. A navigation performed by navigate() from an onClick handler is attributed correctly. The difference is where the handler runs: the router attaches its anchor handler to document directly, outside the web runtime's interaction frame.
Where
src/data/events.ts, setupNativeEvents:
// ensure delegated event run first
delegateEvents(["click", "submit"]);
document.addEventListener("click", handleAnchorClick);
if (preload) {
document.addEventListener("mousemove", handleAnchorMove, { passive: true });
document.addEventListener("focusin", handleAnchorPreload, { passive: true });
document.addEventListener("touchstart", handleAnchorPreload, { passive: true });
}
document.addEventListener("submit", handleFormSubmit);
@solidjs/web wraps every handler it dispatches — delegated events via eventHandler, runtime-attached ones via addEvent — in dispatchAsInteraction, i.e. OBSERVE.attribution.withInteraction({ type, target, at }, fn), so every root write inside the handler (the router's location write included) is attributed to that interaction. A raw document.addEventListener goes around that wrapper. handleAnchorClick then calls navigateFromRoute, whose withOrigin(describeNavigation…) frame opens with no enclosing interaction, so the record is an orphan.
handleFormSubmit has the same shape: an action submitted through a native <form> is unattributed, while one submitted from a handler is not.
Observed
With @sentry/solid-2 consuming the records (e2e app on rc.13 / next.32, / → /users/6):
<button onClick={() => navigate('/users/6')}>:NavigationEvent.interactionis the click; the click span links to the route-named navigation span.<a href="/users/6">:NavigationEvent.interaction === undefined; there is no click span at all, since no interaction frame ever opened. The navigation and its server-function call stand alone. The INP-relevant facts on the interaction record (inputDelayMs,handlerMs,settledMs) are lost for every link click in the app — which is most navigations.
The consumer documents the caveat for now rather than guessing a parent by time.
Cause
The direct document listeners date from the ordering requirement noted in the comment — Solid's delegated click must run first so a component's onClick with preventDefault() can stop the navigation — and predate the runtime having an interaction frame to run under. That ordering still has to hold; the fix is to run the handler inside the frame, not to change when it runs.
Options
- Router wraps its handlers. In
setupNativeEvents, whenOBSERVEis defined, dispatchhandleAnchorClickandhandleFormSubmitthroughOBSERVE.attribution.withInteraction({ type: evt.type, target: …, at: evt.timeStamp }, () => handler(evt)). Smallest change, but it duplicates the web runtime'sdescribeEventTarget(element description, thevaluesprivacy gate for text) andinteractionStart(thetimeStampclock check), which the router should not own. - Web exposes the frame.
@solidjs/webgains a small public entry — a listener attach that wraps under observe and is the identity function otherwise (addEvent(node, name, handler, false)already does exactly this but is marked@internal, compiler-emitted). The router uses it for theclickandsubmitlisteners. Preload listeners (mousemove,focusin,touchstart) stay raw: preloading is not a user interaction and should not open frames. - Web stamps
document-level listeners itself. Not viable without patchingEventTarget.prototype; not proposed.
(2) is the right shape: the web runtime owns interaction description, the router only needs "run this as the event's handler". It is a public-surface addition on @solidjs/web, so it needs a decision there first; (1) can land in the router alone if that is preferred short-term.
Either way the order relative to Solid's delegated handler must not change: attach after delegateEvents(["click", "submit"]) exactly as today, so evt.defaultPrevented still reflects component handlers.
Acceptance
- An anchor click that navigates produces a
NavigationEventwhoseinteractionis the click'sInteractionRef(typeclick, targeta#…), the same object identity anavigate()fromonClickgets today. - A
<form>submitted to an action produces an interaction of typesubmiton the action's records. - A component
onClickcallingpreventDefault()still stops the anchor navigation. - Nothing changes in non-observe builds (the wrapper folds to the plain listener).
Related: solidjs/solid#3683 (route declaration to the observe tier), getsentry/sentry-javascript#24517 (consumer; the caveat is documented in docs/solid-2-observe.md there).
— Claude via Cursor
- Vorherrschende Sprache
- TypeScript
- Sterne
- 1.3k
- Forks
- 183
- Ø Merge
- 14 Std. 35 Min.
- Gemergte PRs (30 T.)
- 52
Entwicklungsumgebung
- Kein Dockerfile und keine Docker-Compose-Datei
- Keine Pull-Request-Vorlage
- Beitragsleitfaden lesen
Erste Schritte
- Lesen Sie das ganze Issue und danach den Beitragsleitfaden des Projekts.
- Schreiben Sie ins Issue, dass Sie es übernehmen — das erspart doppelte Arbeit.
- Forken Sie das Repository und arbeiten Sie in einem Branch.
- Öffnen Sie einen Pull Request, der die Issue-Nummer nennt.
Mehr aus solidjs/solid-router
-
Forward pressed while a Back navigation is still loading is dropped; the URL and the rendered route get out of syncEvtl. vergeben @sean0407 hat das heute übernommen. Offen
Schwierigkeit 4/5 1-2 Tage Anfängerfreundlichkeit 54/100
solidjs/solid-router#687 ·
Maintainer antworten meist innerhalb von 1 Tag
-
<A> costs ~6us of server CPU per instance during SSR (20x a plain <a>), mostly mergeProps/splitPropsEvtl. vergeben @birkskyum hat das vor 71 Tagen übernommen. Offen1.x
Schwierigkeit 4/5 3-5 Tage Anfängerfreundlichkeit 55/100
solidjs/solid-router#583 ·
Maintainer antworten meist innerhalb von 1 Tag
-
1.x enhancement
Schwierigkeit 3/5 1-2 Tage Anfängerfreundlichkeit 38/100
solidjs/solid-router#518 · 2 Kommentare ·
Maintainer antworten meist innerhalb von 1 Tag
-
Schwierigkeit 4/5 3-5 Tage Anfängerfreundlichkeit 35/100
solidjs/solid-router#482 · 2 Kommentare ·
Maintainer antworten meist innerhalb von 1 Tag
-
enhancement
Schwierigkeit 4/5 3-5 Tage Anfängerfreundlichkeit 25/100
solidjs/solid-router#459 · 2 Kommentare ·
Maintainer antworten meist innerhalb von 1 Tag
Alle Issues in solidjs/solid-router
Ähnliche Issues
-
area: app type: bug
Schwierigkeit 2/5 1-3 Stunden Anfängerfreundlichkeit 78/100
ExpidetGames/code-reviewer#585 ·
Maintainer antworten meist innerhalb von 1 Tag
-
Schwierigkeit 1/5 Unter einer Stunde Anfängerfreundlichkeit 83/100
module-federation/core#5205 ·
Maintainer antworten meist innerhalb von 1 Tag
-
Schwierigkeit 2/5 1-3 Stunden Anfängerfreundlichkeit 73/100
LanternOps/breeze#9392 · 1 Kommentar ·
Maintainer antworten meist innerhalb von 1 Tag
-
engine-rs P3 review-deferral wasm
Schwierigkeit 2/5 1-3 Stunden Anfängerfreundlichkeit 77/100
maniator/verticopolis#1154 ·
Maintainer antworten meist innerhalb von 1 Tag
-
Schwierigkeit 2/5 1-3 Stunden Anfängerfreundlichkeit 78/100
Maintainer antworten meist innerhalb von 1 Tag