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

Svelte 5 insert row gives very poor performance #5758

Open
2 tasks done
prince-jagani opened this issue Sep 25, 2024 · 0 comments
Open
2 tasks done

Svelte 5 insert row gives very poor performance #5758

prince-jagani opened this issue Sep 25, 2024 · 0 comments

Comments

@prince-jagani
Copy link

prince-jagani commented Sep 25, 2024

TanStack Table version

v9.0.0-alpha.10

Framework/Library version

Svelte 5.0.0-next.244

Describe the bug and the steps to reproduce it

Hello, I've been using Tanstack Table v9 with svelte 5 + sveltekit and getting weird performance issue.

This is the function to insert a new row at starting of the table. I'm updating table data and inserting a new row with websocket message that is coming every one second from server. Basically I'm inserting a new row every 1 second and it gives weird console warnings and after 50-60 seconds application starts lagging and eventually crashes. I've attached console log warnings below.

I've noticed some other important points related to this:

  1. If I insert a new row every 5 second instead of every 1 second, issue still persist
  2. If I have applied filters on the data such that no data will be in list then it do not lag.(e.g. if age is ranged 0 to 30 and filter it to min 31)
  3. As many rows I insert lag and pause time increases. Almost same time as the console warning
  4. Debouncing the rowModel = table.getRowModel(); isn't working at all
  • Tanstack Table Version: ^9.0.0-alpha.10
  • Svelte: ^5.0.0-next.244
  • Sveltekit: ^2.0.0
  • @sveltejs/vite-plugin-svelte: ^4.0.0-next.6

I assume that this is rendering related issue.. I've also attached snippet for how i'm rendering the table.

export const insertNewRow = (rowData) => {

		if (isAnimatingRow) return;
		animateInsertRow = true;
		isAnimatingRow = true;
		document.getElementById('main-layout').scrollTo({ top: 0, behavior: 'smooth' });

		data = [rowData, ...data.slice(0, 49)];

		setTimeout(() => {
			animateInsertRow = false;
			isAnimatingRow = false;
		}, 500);
	};

      //other code

$effect(() => {
		if (sorting || filters || data) {
			rowModel = table.getRowModel();
		}
	});
<div class="table select-none flex text-xs md:text-sm w-full">
	<div class="table-root sticky top-0 flex flex-col">
		<div
			class={`relative table-header grid border-b-2 border-border sticky top-[52px] z-10 lg:rounded-t-md`}
			style:grid-template-columns={`${tableGridLayout}`}
			bind:this={gridHeaderLayout}
		>
			{#each table.getHeaderGroups() as headerGroup, ind (ind)}
				{#each headerGroup.headers as header, index (index)}
					<div
						class="table-header-cell border-b border-borderLight bg-card px-4 h-10 flex items-center grow-1"
						class:sticky={header.column.columnDef.pinned}
						class:left-0={header.column.columnDef.pinned}
						class:z-10={header.column.columnDef.pinned}
						style:top={`${headerTopOffset}px`}
						style:left={`${header.column.columnDef.leftOffset || 0}px`}
						class:justify-end={index !== 0}
						class:border-r={index !== headerGroup.headers.length - 1}
					>
						{#if !header.isPlaceholder}
							{#if header.column.getCanSort()}
								<button
									class="flex gap-2"
									onclick={() => {
										console.log(sorting[0]);
										if (sorting[0] && sorting[0].id === header.column.columnDef.accessorKey) {
											updateExternalSort(
												header.column.columnDef.accessorKey,
												sorting[0] ? (sorting[0].desc ? 'asc' : 'none') : 'desc'
											);
										} else {
											updateExternalSort(header.column.columnDef.accessorKey, 'desc');
										}
									}}
								>
									{#if typeof header.column.columnDef.header === 'function'}
										{header.column.columnDef.header()}
									{:else}
										{header.column.columnDef.header}
									{/if}

									{#if header.column.getIsSorted().toString() === 'asc'}
										<PrimeSortUpFill />
									{:else if header.column.getIsSorted().toString() === 'desc'}
										<PrimeSortDownFill />
									{/if}
								</button>
							{:else if typeof header.column.columnDef.header === 'function'}
								{header.column.columnDef.header()}
							{:else}
								{header.column.columnDef.header}
							{/if}
						{/if}
					</div>
				{/each}
			{/each}
		</div>
		<div
			class={`relative flex-grow table-body ${rowModel.rows.length === 0 && 'h-[calc(100vh-359px)] sm:h-[calc(100vh-301px)] md:h-[calc(100vh-319px)]'}`}
			bind:this={tableBody}
		>
			{#if isLoading}
				<TableLoader gridLayout={tableGridLayout} columns={columnDef.length} />
			{:else if rowModel.rows.length === 0}
				<div class={`size-full min-h-full max-w-[100vw] lg:max-w-[calc(100vw-256px)] bg-card p-4`}>
					<div
						class="text-center p-4 border border-dashed min-h-full rounded-button text-xl flex items-center justify-center"
					>
						<span class="text-highlight">{notFound}</span>
					</div>
				</div>
			{:else}
				{#each rowModel.rows as row, rowIndex (row.original.id)}
					<div
						class={`table-row grid group`}
						style:grid-template-columns={tableGridLayout}
						animate:flip={{ duration: 300 }}
						in:fly={getTransition(rowIndex)}
						out:slide={{ duration: 300 }}
					>
						<!-- Maybe only this:
					in:fly="{{ y: rowIndex === 0 && animateInsertRow ? 50 : 0, duration: 300 }}" -->
						{#each row.getVisibleCells() as cell, cellIndex (cellIndex)}
							<div
								class="table-cell p-3 flex items-center border-b border-borderLight grow-1 group-hover:bg-modal"
								class:pinned={cell.column.columnDef.pinned}
								class:bg-background={cell.column.columnDef.pinned}
								class:border-b-0={rowIndex === rowModel.rows.length - 1}
								class:lg:rounded-bl-md={rowIndex === rowModel.rows.length - 1 && cellIndex === 0}
								class:lg:rounded-br-md={rowIndex === rowModel.rows.length - 1 &&
									cellIndex === row.getVisibleCells().length - 1}
								class:border-r={cellIndex !== row.getVisibleCells().length - 1}
								style:left={`${cell.column.columnDef.leftOffset || 0}px`}
								class:justify-end={cellIndex !== 0}
							>
								{#if cell.column.columnDef.component}
									{@const { component: CustomComponent, props } = cell.column.columnDef.cell(
										cell.getContext()
									)}
									<CustomComponent {...props} />
								{:else}
									{cell.getValue()}
								{/if}
							</div>
						{/each}
					</div>
				{/each}
			{/if}
		</div>
	</div>
</div>

Image

Your Minimal, Reproducible Example - (Sandbox Highly Recommended)

'

Screenshots or Videos (Optional)

No response

Do you intend to try to help solve this bug with your own PR?

None

Terms & Code of Conduct

  • I agree to follow this project's Code of Conduct
  • 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.
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

No branches or pull requests

1 participant