Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve Solid adapter. #790

Open
wants to merge 1 commit into
base: main
Choose a base branch
from

Conversation

martinpengellyphillips
Copy link

I encountered some issues using the Solid adapter with the latest Solid version (1.8). In particular, no items would display unless I added into my code a deferred setting of the element ref (e.g. ref={(el) => queueMicrotask(() => setRef(el))}).

Looking through the source I believe the issue stems from _willUpdate being called with a scrollElement that has not yet been connected to a targetWindow (due to the use of createComputed). This PR attempts to avoid this issue and the need for a workaround in consumer code as well as make a few other changes for optimisation and to maintain reactivity expectations.

--

Use createEffect to ensure scrollElement ref is connected to DOM and ownerDocument/window before attempting to update measurements for it. Otherwise, virtualizer.targetWindow will be set to null (in _willUpdate), the scrollElement rect to nothing and no items will be displayed.

In addition, remove some logic that causes redundant work to be done (e.g. setOptions called multiple times, _willUpdate called on mount which is a no-op if the scollElement didn't change). Instead rely on the options reactivity to perform the bulk of the work.

Also, reset virtual items store when options change to ensure that reactivity is maintained - e.g. so that measureItem is called again in a <For> loop if scrollMargin changed.

Use `createEffect` to ensure scrollElement ref is connected to DOM
and ownerDocument/window before attempting to update measurements
for it. Otherwise, `virtualizer.targetWindow` will be set to null
(in _willUpdate), the scrollElement rect to nothing and no items
will be displayed.

In addition, remove some logic that causes redundant work to be
done (e.g. `setOptions` called multiple times, `_willUpdate`
called on mount which is a no-op if the scollElement didn't change). Instead rely on the options reactivity to perform the
bulk of the work.

Also, reset virtual items store when options change to ensure that
reactivity is maintained - e.g. so that `measureItem` is called
again in a `<For>` loop if `scrollMargin` changed.
virtualizer.setOptions(
mergeProps(resolvedOptions, options, {
onChange: (
instance: Virtualizer<TScrollElement, TItemElement>,
sync: boolean,
) => {
instance._willUpdate()
setVirtualItems(
reconcile(instance.getVirtualItems(), {
key: 'index',

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should also make this 'key' rather than 'index' so that it uses any custom supplied key from getItemKey option for the diff.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yep, it should be key

virtualizer.setOptions(
mergeProps(resolvedOptions, options, {
onChange: (
instance: Virtualizer<TScrollElement, TItemElement>,
sync: boolean,
) => {
instance._willUpdate()
setVirtualItems(

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should batch the set state calls together.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What do you suggest here?

@piecyk
Copy link
Collaborator

piecyk commented Aug 15, 2024

@martinpengellyphillips big thanks for this, could you add also some test to check the basic stuff 🙏 😉 ?

@martinpengellyphillips
Copy link
Author

@martinpengellyphillips big thanks for this, could you add also some test to check the basic stuff 🙏 😉 ?

@piecyk Sure! Should I follow general approach to tests from the react adapter?

@piecyk
Copy link
Collaborator

piecyk commented Aug 16, 2024

@martinpengellyphillips big thanks for this, could you add also some test to check the basic stuff 🙏 😉 ?

@piecyk Sure! Should I follow general approach to tests from the react adapter?

Could be, or you can try playwright, have it on todo for some time. Overall what you feel more comfortable with, we need to start with something.

Copy link

nx-cloud bot commented Aug 22, 2024

☁️ Nx Cloud Report

CI is running/has finished running commands for commit 00fd6fb. As they complete they will appear below. Click to see the status, the terminal output, and the build insights.

📂 See all runs for this CI Pipeline Execution


✅ Successfully ran 2 targets

Sent with 💌 from NxCloud.

Copy link

pkg-pr-new bot commented Aug 22, 2024

commit: 00fd6fb

@tanstack/lit-virtual

pnpm add https://pkg.pr.new/@tanstack/lit-virtual@790

@tanstack/react-virtual

pnpm add https://pkg.pr.new/@tanstack/react-virtual@790

@tanstack/solid-virtual

pnpm add https://pkg.pr.new/@tanstack/solid-virtual@790

@tanstack/svelte-virtual

pnpm add https://pkg.pr.new/@tanstack/svelte-virtual@790

@tanstack/virtual-core

pnpm add https://pkg.pr.new/@tanstack/virtual-core@790

@tanstack/vue-virtual

pnpm add https://pkg.pr.new/@tanstack/vue-virtual@790

Open in Stackblitz

More templates

virtualizer.setOptions(
mergeProps(resolvedOptions, options, {
onChange: (
instance: Virtualizer<TScrollElement, TItemElement>,
sync: boolean,
) => {
instance._willUpdate()
setVirtualItems(
reconcile(instance.getVirtualItems(), {
key: 'index',
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yep, it should be key

virtualizer.setOptions(
mergeProps(resolvedOptions, options, {
onChange: (
instance: Virtualizer<TScrollElement, TItemElement>,
sync: boolean,
) => {
instance._willUpdate()
setVirtualItems(
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What do you suggest here?

@@ -81,6 +78,8 @@ function createVirtualizerBase<
},
}),
)
setVirtualItems([])
virtualizer._willUpdate()
virtualizer.measure()
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Btw the measure here looks suspicious

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants