表格状态 (Svelte) 指南

表格状态 (Svelte) 指南

TanStack Table 具有一个简单的底层内部状态管理系统,用于存储和管理表格的状态。它还允许您有选择地提取您需要在自己的状态管理中管理的任何状态。本指南将引导您了解与表格状态交互和管理的不同方式。

访问表格状态

您无需设置任何特殊内容即可使表格状态工作。如果您在 stateinitialState 或任何 on[State]Change 表格选项中未传入任何内容,则表格将在内部管理其自身的状态。您可以使用 table.getState() 表格实例 API 访问此内部状态的任何部分。

jsx
const options = writable({
  columns,
  data,
  //...
})

const table = createSvelteTable(options)

console.log(table.getState()) //access the entire internal state
console.log(table.getState().rowSelection) //access just the row selection state
const options = writable({
  columns,
  data,
  //...
})

const table = createSvelteTable(options)

console.log(table.getState()) //access the entire internal state
console.log(table.getState().rowSelection) //access just the row selection state

自定义初始状态

如果对于某些状态,您只需要自定义其初始默认值,则仍然无需自己管理任何状态。您只需在表格实例的 initialState 选项中设置值即可。

jsx
const options = writable({
  columns,
  data,
  initialState: {
    columnOrder: ['age', 'firstName', 'lastName'], //customize the initial column order
    columnVisibility: {
      id: false //hide the id column by default
    },
    expanded: true, //expand all rows by default
    sorting: [
      {
        id: 'age',
        desc: true //sort by age in descending order by default
      }
    ]
  },
  //...
})

const table = createSvelteTable(options)
const options = writable({
  columns,
  data,
  initialState: {
    columnOrder: ['age', 'firstName', 'lastName'], //customize the initial column order
    columnVisibility: {
      id: false //hide the id column by default
    },
    expanded: true, //expand all rows by default
    sorting: [
      {
        id: 'age',
        desc: true //sort by age in descending order by default
      }
    ]
  },
  //...
})

const table = createSvelteTable(options)

注意:仅在 initialStatestate 中指定每个特定状态,但不要同时在两者中指定。如果您将特定状态值同时传递给 initialStatestate,则 state 中的初始化状态将覆盖 initialState 中的任何对应值。

受控状态

如果您需要在应用程序的其他区域轻松访问表格状态,TanStack Table 可以轻松地在您自己的状态管理系统中控制和管理任何或所有表格状态。您可以通过将您自己的状态和状态管理函数传递给 stateon[State]Change 表格选项来实现此目的。

单独受控状态

您可以仅控制您需要轻松访问的状态。如果您不需要,则不必控制所有表格状态。建议仅根据具体情况控制您需要的状态。

为了控制特定状态,您需要同时将相应的 state 值和 on[State]Change 函数传递给表格实例。

让我们以“手动”服务器端数据获取场景中的筛选、排序和分页为例。您可以将筛选、排序和分页状态存储在您自己的状态管理中,但如果您 的 API 不关心这些值,则可以忽略任何其他状态,例如列顺序、列可见性等。

ts
let sorting = [
  {
    id: 'age',
    desc: true, //sort by age in descending order by default
  },
]
const setSorting = updater => {
  if (updater instanceof Function) {
    sorting = updater(sorting)
  } else {
    sorting = updater
  }
  options.update(old => ({
    ...old,
    state: {
      ...old.state,
      sorting,
    },
  }))
}

let columnFilters = [] //no default filters
const setColumnFilters = updater => {
  if (updater instanceof Function) {
    columnFilters = updater(columnFilters)
  } else {
    columnFilters = updater
  }
  options.update(old => ({
    ...old,
    state: {
      ...old.state,
      columnFilters,
    },
  }))
}

let pagination = { pageIndex: 0, pageSize: 15 } //default pagination
const setPagination = updater => {
  if (updater instanceof Function) {
    pagination = updater(pagination)
  } else {
    pagination = updater
  }
  options.update(old => ({
    ...old,
    state: {
      ...old.state,
      pagination,
    },
  }))
}

//Use our controlled state values to fetch data
const tableQuery = createQuery({
  queryKey: ['users', columnFilters, sorting, pagination],
  queryFn: () => fetchUsers(columnFilters, sorting, pagination),
  //...
})

const options = writable({
  columns,
  data: tableQuery.data,
  //...
  state: {
    columnFilters, //pass controlled state back to the table (overrides internal state)
    sorting,
    pagination
  },
  onColumnFiltersChange: setColumnFilters, //hoist columnFilters state into our own state management
  onSortingChange: setSorting,
  onPaginationChange: setPagination,
})

const table = createSvelteTable(options)
//...
let sorting = [
  {
    id: 'age',
    desc: true, //sort by age in descending order by default
  },
]
const setSorting = updater => {
  if (updater instanceof Function) {
    sorting = updater(sorting)
  } else {
    sorting = updater
  }
  options.update(old => ({
    ...old,
    state: {
      ...old.state,
      sorting,
    },
  }))
}

let columnFilters = [] //no default filters
const setColumnFilters = updater => {
  if (updater instanceof Function) {
    columnFilters = updater(columnFilters)
  } else {
    columnFilters = updater
  }
  options.update(old => ({
    ...old,
    state: {
      ...old.state,
      columnFilters,
    },
  }))
}

let pagination = { pageIndex: 0, pageSize: 15 } //default pagination
const setPagination = updater => {
  if (updater instanceof Function) {
    pagination = updater(pagination)
  } else {
    pagination = updater
  }
  options.update(old => ({
    ...old,
    state: {
      ...old.state,
      pagination,
    },
  }))
}

//Use our controlled state values to fetch data
const tableQuery = createQuery({
  queryKey: ['users', columnFilters, sorting, pagination],
  queryFn: () => fetchUsers(columnFilters, sorting, pagination),
  //...
})

const options = writable({
  columns,
  data: tableQuery.data,
  //...
  state: {
    columnFilters, //pass controlled state back to the table (overrides internal state)
    sorting,
    pagination
  },
  onColumnFiltersChange: setColumnFilters, //hoist columnFilters state into our own state management
  onSortingChange: setSorting,
  onPaginationChange: setPagination,
})

const table = createSvelteTable(options)
//...

完全受控状态

或者,您可以使用 onStateChange 表格选项控制整个表格状态。它会将整个表格状态提升到您自己的状态管理系统中。请注意这种方法,因为您可能会发现将某些频繁更改的状态值(如 columnSizingInfo 状态)提升到 svelte 树中可能会导致糟糕的性能问题。

可能需要更多技巧才能使此方法奏效。如果您使用 onStateChange 表格选项,则 state 的初始值必须填充您要使用的所有功能的所有相关状态值。您可以手动键入所有初始状态值,或以特殊方式使用 table.setOptions API,如下所示。

jsx
//create a table instance with default state values
const options = writable({
  columns,
  data,
  //... Note: `state` values are NOT passed in yet
})
const table = createSvelteTable(options)

let state = {
  ...table.initialState, //populate the initial state with all of the default state values from the table instance
  pagination: {
    pageIndex: 0,
    pageSize: 15 //optionally customize the initial pagination state.
  }
}
const setState = updater => {
  if (updater instanceof Function) {
    state = updater(state)
  } else {
    state = updater
  }
  options.update(old => ({
    ...old,
    state,
  }))
}

//Use the table.setOptions API to merge our fully controlled state onto the table instance
table.setOptions(prev => ({
  ...prev, //preserve any other options that we have set up above
  state, //our fully controlled state overrides the internal state
  onStateChange: setState //any state changes will be pushed up to our own state management
}))
//create a table instance with default state values
const options = writable({
  columns,
  data,
  //... Note: `state` values are NOT passed in yet
})
const table = createSvelteTable(options)

let state = {
  ...table.initialState, //populate the initial state with all of the default state values from the table instance
  pagination: {
    pageIndex: 0,
    pageSize: 15 //optionally customize the initial pagination state.
  }
}
const setState = updater => {
  if (updater instanceof Function) {
    state = updater(state)
  } else {
    state = updater
  }
  options.update(old => ({
    ...old,
    state,
  }))
}

//Use the table.setOptions API to merge our fully controlled state onto the table instance
table.setOptions(prev => ({
  ...prev, //preserve any other options that we have set up above
  state, //our fully controlled state overrides the internal state
  onStateChange: setState //any state changes will be pushed up to our own state management
}))

状态更改回调

到目前为止,我们已经看到了 on[State]ChangeonStateChange 表格选项的工作方式是将表格状态更改“提升”到我们自己的状态管理中。但是,关于使用这些选项,您应该注意一些事项。

1. 状态更改回调必须在 state 选项中具有其对应的状态值

指定 on[State]Change 回调会告知表格实例这将是一个受控状态。如果您未指定相应的 state 值,则该状态将“冻结”为其初始值。

ts
let sorting = []
const setSorting = updater => {
  if (updater instanceof Function) {
    sorting = updater(sorting)
  } else {
    sorting = updater
  }
  options.update(old => ({
    ...old,
    state: {
      ...old.state,
      sorting,
    },
  }))
}
//...
const options = writable({
  columns,
  data,
  //...
  state: {
    sorting, //required because we are using `onSortingChange`
  },
  onSortingChange: setSorting, //makes the `state.sorting` controlled
})
const table = createSvelteTable(options)
let sorting = []
const setSorting = updater => {
  if (updater instanceof Function) {
    sorting = updater(sorting)
  } else {
    sorting = updater
  }
  options.update(old => ({
    ...old,
    state: {
      ...old.state,
      sorting,
    },
  }))
}
//...
const options = writable({
  columns,
  data,
  //...
  state: {
    sorting, //required because we are using `onSortingChange`
  },
  onSortingChange: setSorting, //makes the `state.sorting` controlled
})
const table = createSvelteTable(options)

2. 更新器可以是原始值或回调函数

on[State]ChangeonStateChange 回调的工作方式与 React 中的 setState 函数完全相同。更新器值可以是新的状态值,也可以是接受先前状态值并返回新状态值的回调函数。

这有什么含义?这意味着,如果您想在任何 on[State]Change 回调中添加一些额外的逻辑,您可以这样做,但您需要检查新的传入更新器值是函数还是值。

这就是为什么您在上面示例的 setState 函数中看到 if (updater instanceof Function) 检查的原因。

状态类型

TanStack Table 中的所有复杂状态都有自己的 TypeScript 类型,您可以导入和使用。这对于确保您为要控制的状态值使用正确的数据结构和属性非常有用。

ts
import { createSvelteTable, type SortingState, type Updater } from '@tanstack/svelte-table'
//...
let sorting: SortingState[] = [
  {
    id: 'age', //you should get autocomplete for the `id` and `desc` properties
    desc: true,
  }
]
const setSorting = (updater: Updater<SortingState>)  => {
  if (updater instanceof Function) {
    sorting = updater(sorting)
  } else {
    sorting = updater
  }
  options.update(old => ({
    ...old,
    state: {
      ...old.state,
      sorting,
    },
  }))
}
import { createSvelteTable, type SortingState, type Updater } from '@tanstack/svelte-table'
//...
let sorting: SortingState[] = [
  {
    id: 'age', //you should get autocomplete for the `id` and `desc` properties
    desc: true,
  }
]
const setSorting = (updater: Updater<SortingState>)  => {
  if (updater instanceof Function) {
    sorting = updater(sorting)
  } else {
    sorting = updater
  }
  options.update(old => ({
    ...old,
    state: {
      ...old.state,
      sorting,
    },
  }))
}
订阅 Bytes

您的每周 JavaScript 新闻。每周一免费发送给超过 100,000 名开发者。

Bytes

无垃圾邮件。随时取消订阅。