virtual icon indicating copy to clipboard operation
virtual copied to clipboard

SolidJS: warning "Missing attribute name 'data-index={index}' on measured element."

Open Azq2 opened this issue 10 months ago • 3 comments

Describe the bug

Looks like virtualizer.measureElement is not working with SolidJS

<For each={virtualizer.getVirtualItems()}>{(item) =>
	<div
		class={item.index % 2 ? 'ListItemOdd' : 'ListItemEven'}
		data-index={item.index}
		ref={virtualizer.measureElement}
		style={{
			border: "1px solid red",
			"box-sizing": "border-box",
			"height": "150px"
		}}
	>
		Row {item.index} 
	</div>
}</For>

Dirty workaround:

<For each={virtualizer.getVirtualItems()}>{(item) =>
	<div
		class={item.index % 2 ? 'ListItemOdd' : 'ListItemEven'}
		data-index={item.index}
		ref={(el) => {
			el.dataset.index = item.index.toString(); // <--- see this!
			virtualizer.measureElement(el);
		}}
		style={{
			border: "1px solid red",
			"box-sizing": "border-box",
			"height": "150px"
		}}
	>
		Row {item.index} {Date.now()}
	</div>
}</For>

Your minimal, reproducible example

https://codesandbox.io/p/devbox/9rkhxf

Steps to reproduce

Just add

data-index={item.index}
ref={virtualizer.measureElement}

Expected behavior

No warning

How often does this bug happen?

None

Screenshots or Videos

No response

Platform

Chromium 133.0.6943.98

tanstack-virtual version

3.13.0

TypeScript version

No response

Additional context

No response

Terms & Code of Conduct

  • [x] I agree to follow this project's Code of Conduct
  • [x] I understand that if my bug cannot be reliable reproduced in a debuggable environment, it will probably not be fixed and this issue may even be closed.

Azq2 avatar Feb 18 '25 23:02 Azq2

i seem to be able to work around this particular issue by setting the data-index attribute in the ref callback:

ref={(el) => {
	el.dataset.index = `${row.index}`;
	virtualizer.measureElement(el);
}}

still having other problems like the measured height only affecting the total size when scrolling... and only getting that far when wrapping the createVirtualizer call in a createMemo (because my count changes with every infiniteQuery.fetchNextPage), which i don't even know i'm supposed to do or not (edit: okay, i'm pretty sure i shouldn't do that as it'll re-initialize the virtualizer on every data change, which i don't want. an effect that sets virtualizer.options.count to the updated count seems to work, though). i'd love to see a working, best practice example tbh

quick update: in this example, they're doing this:

ref={(el) => queueMicrotask(() => virtualizer.measureElement(el))}

i don't know if that's the way to go or not, but it seems to work far better than my hack

sk22 avatar Jun 05 '25 20:06 sk22

The data-index={index} is same as createRenderEffect(() => el.dataset["index"] = index), which is run after the ref callback, so the attribute is not exists at the moment. You can use onMount (or createEffect) to schedule the task behind the render effect.

thislight avatar Aug 12 '25 02:08 thislight

Now I use virtua

Azq2 avatar Aug 14 '25 22:08 Azq2