Skip to content

Commit 6e27304

Browse files
fix(Table): improve data reactivity (#3967)
Co-authored-by: Benjamin Canac <[email protected]>
1 parent b4f8ac7 commit 6e27304

File tree

2 files changed

+36
-5
lines changed

2 files changed

+36
-5
lines changed

playground/app/pages/components/table.vue

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -143,6 +143,8 @@ const data = ref<Payment[]>([{
143143
amount: 567
144144
}])
145145
146+
const currentID = ref(4601)
147+
146148
const columns: TableColumn<Payment>[] = [{
147149
id: 'select',
148150
header: ({ table }) => h(UCheckbox, {
@@ -277,8 +279,19 @@ const pagination = ref({
277279
pageSize: 10
278280
})
279281
282+
function addElement() {
283+
data.value.unshift({
284+
id: currentID.value.toString(),
285+
date: new Date().toISOString(),
286+
status: 'paid',
287+
288+
amount: Math.random() * 1000
289+
})
290+
currentID.value++
291+
}
292+
280293
function randomize() {
281-
data.value = [...data.value].sort(() => Math.random() - 0.5)
294+
data.value = data.value.sort(() => Math.random() - 0.5)
282295
}
283296
284297
function onSelect(row: TableRow<Payment>) {
@@ -303,6 +316,7 @@ onMounted(() => {
303316
/>
304317

305318
<UButton color="neutral" label="Randomize" @click="randomize" />
319+
<UButton color="neutral" label="Add element" @click="addElement" />
306320

307321
<UDropdownMenu
308322
:items="table?.tableApi?.getAllColumns().filter(column => column.getCanHide()).map(column => ({

src/runtime/components/Table.vue

Lines changed: 21 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
<!-- eslint-disable vue/block-tag-newline -->
22
<script lang="ts">
3-
import type { Ref } from 'vue'
3+
import type { Ref, WatchOptions } from 'vue'
44
import type { AppConfig } from '@nuxt/schema'
55
import type { Cell, Header, RowData, TableMeta } from '@tanstack/table-core'
66
import type {
@@ -97,6 +97,13 @@ export interface TableProps<T extends TableData> extends TableOptions<T> {
9797
* @defaultValue 'carousel'
9898
*/
9999
loadingAnimation?: Table['variants']['loadingAnimation']
100+
/**
101+
* Use the `watchOptions` prop to customize reactivity (for ex: disable deep watching for changes in your data or limiting the max traversal depth). This can improve performance by reducing unnecessary re-renders, but it should be used with caution as it may lead to unexpected behavior if not managed properly.
102+
* @link [API Docs](https://vuejs.org/api/options-state.html#watch)
103+
* @link [Guide](https://vuejs.org/guide/essentials/watchers.html)
104+
* @defaultValue { deep: true }
105+
*/
106+
watchOptions?: WatchOptions
100107
/**
101108
* @link [API Docs](https://tanstack.com/table/v8/docs/api/features/global-filtering#table-options)
102109
* @link [Guide](https://tanstack.com/table/v8/docs/guide/global-filtering)
@@ -175,7 +182,7 @@ export type TableSlots<T> = {
175182
</script>
176183

177184
<script setup lang="ts" generic="T extends TableData">
178-
import { computed, ref } from 'vue'
185+
import { computed, ref, watch } from 'vue'
179186
import { Primitive } from 'reka-ui'
180187
import { upperFirst } from 'scule'
181188
import { FlexRender, getCoreRowModel, getFilteredRowModel, getSortedRowModel, getExpandedRowModel, useVueTable } from '@tanstack/vue-table'
@@ -184,13 +191,17 @@ import { useAppConfig } from '#imports'
184191
import { useLocale } from '../composables/useLocale'
185192
import { tv } from '../utils/tv'
186193
187-
const props = defineProps<TableProps<T>>()
194+
const props = withDefaults(defineProps<TableProps<T>>(), {
195+
watchOptions: () => ({
196+
deep: true
197+
})
198+
})
188199
const slots = defineSlots<TableSlots<T>>()
189200
190201
const { t } = useLocale()
191202
const appConfig = useAppConfig() as Table['AppConfig']
192203
193-
const data = computed(() => props.data ?? [])
204+
const data = ref(props.data ?? []) as Ref<T[]>
194205
const columns = computed<TableColumn<T>[]>(() => props.columns ?? Object.keys(data.value[0] ?? {}).map((accessorKey: string) => ({ accessorKey, header: upperFirst(accessorKey) })))
195206
const meta = computed(() => props.meta ?? {})
196207
@@ -314,6 +325,12 @@ function handleRowSelect(row: TableRow<T>, e: Event) {
314325
props.onSelect(row, e)
315326
}
316327
328+
watch(
329+
() => props.data, () => {
330+
data.value = props.data ? [...props.data] : []
331+
}, props.watchOptions
332+
)
333+
317334
defineExpose({
318335
tableRef,
319336
tableApi

0 commit comments

Comments
 (0)