Replies: 1 comment 1 reply
|
Thank you for bringing this up, it will be handled in the next release w/ #8029 |
1 reply
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Uh oh!
There was an error while loading. Please reload this page.
Problem
With
preload="viewport", a route is preloaded as soon as the link intersects theobserver zone (
rootMargin: 100px). The IntersectionObserver callback callsdoPreload()on the first intersecting entry, immediately.preloadDelayonlyapplies to intent preloading (mouse enter, touch start, focus), so there is no way
to soften viewport preloading.
On long scrollable grids this floods the API: every link that flies past during a
fast scroll kicks off its route loader, even though the user never actually saw it.
Repro
The page renders 200 product cards, each a
<Link preload="viewport">whose routehas a loader. A fixed panel counts loader calls, and nothing is ever clicked, so
every call is a preload. One quick scroll through the list drives the counter to
200 out of 200: every card fired its loader, including cards that were visible for
a couple of frames. The links even set
preloadDelay={500}, which has no effectfor viewport preloading.
Proposal
Give viewport preloading dwell semantics:
preloadRouteexactly as todaythe timer again (this matches the current re-fire behavior)
We are running exactly this in production as a thin wrapper around
Link(passing
preload={false}down and drivingrouter.preloadRoutefrom our ownobserver). It is a product catalog in a Telegram Mini App: with a 500 ms dwell
the same fast flick produces zero preloads, and a short rest preloads only the
links that are actually sitting in the viewport.
API question
There are two ways to expose this, and we would like maintainer input before
implementing anything:
preloadDelay/defaultPreloadDelayapply to viewportpreloading as well. Symmetric and adds no new API, but it changes behavior for
apps that already set
defaultPreloadDelayfor hover: their viewport preloadswould suddenly become delayed.
preloadViewportDelay), defaulting to 0so current behavior is preserved. Safer, at the cost of a slightly bigger API.
We lean toward option 1 with a release note, but option 2 is the safer,
behavior-preserving change. Either works for us.
Related implementation note
The viewport observer callback currently reads only the first entry of the batch.
Entries are batched per frame, so during a fast scroll a link can both enter and
leave within one frame, and the batch then contains two transitions for the same
target. The last entry reflects the actual state and should win. This is invisible
today because the callback fires the preload on any intersecting entry, but it
starts to matter once cancellation exists, so it is worth fixing as part of this
change.
Offer
Happy to submit a PR with tests once the direction is agreed. Our production
implementation (a dwell ref callback with cancel-on-exit, based on React 19 ref
cleanup) is ready to be adapted to the current
link.tsxstructure.All reactions