TanStack Table V9 RFC #5834
Unanswered
KevinVandy
asked this question in
Ideas
Replies: 1 comment 1 reply
-
I'm curious. In v8, the plugin architecture was removed, to favor inversion of control: https://tanstack.com/table/v8/docs/guide/migrating#notable-changes. How does this connect?
Really cool 👍 |
Beta Was this translation helpful? Give feedback.
1 reply
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
-
Introduction
TanStack Table V9 is nearing new alpha and beta releases. Significant effort has been dedicated to making TanStack Table a more modular and tree-shakable library. This will enable it to scale its feature set more effectively without introducing unnecessary bloat for features that only a small subset of applications require.
Goals of TanStack Table V9
TanStack does not release new major versions for no reason. Major version releases include breaking changes that are necessary to steer the library back into a more sustainable direction. Here are the main goals we have with the upcoming V9 release:
Lower Priorities (Not in Scope for Initial 9.0 Release)
There are lots of new features that we could add to TanStack Table, but we are not spending time on them yet. TanStack Table V9 is focussed on a new modular architecture, first and foremost. Outside of how the
useTable
hook is set up, we are hoping for easy upgrades.These are all important things that we really want to add to TanStack Table, but we will not be able to ship these without delaying a potential V9 release by an even longer amount of time. Plus, we want to stagger the amount of breaking changes we make to the API to make the upgrade paths as smooth as possible.
Scope of this RFC
This Request for Comments (RFC) focuses specifically on the new syntax and code organization in TanStack Table V9. We aim to keep this discussion targeted and avoid turning it into a broader conversation about individual feature implementations or a wish list for new features. The current goal is to lay the foundation for these enhancements.
This RFC is mostly using React syntax, but the same concepts apply to other frameworks.
Here are some links to TanStack Table V9 alpha examples in different frameworks:
Feedback That We Are Looking For
This is an RFC, so we are looking for feedback on the new code structure, naming conventions, and other changes.
We are not necessarily looking for a big wish list of brand new features right now, unless you are willing to help implement them and get them shipped within the next few months. However, keep in mind that with the new plugin system, you will be able to add your own features to TanStack Table, or even install additional official plugins aside from the stock features that we are initially including. Eventually, we envision many plugins becoming official TanStack Table features.
Overview of Changes
This is not an exhaustive changelog, but a summary of the most important changes that have been worked on so far in the alpha branch.
Renamed
useReactTable
touseTable
,createSvelteTable
tocreateTable
,createAngularTable
toinjectTable
, etc.Tree-Shakable Features:
useTable
hook.table
,column
,row
,cell
, etc. objects) are no longer included in thetable
instance by default. They must be explicitly imported and passed to theuseTable
hook's_features
option._rowModels
table option, similar to_features
.get*RowModel
tocreate*RowModel
.sortFns
,filterFns
, andaggregationFns
are no longer table options and no longer included by default under the hood. They must be imported and passed to the appropriatecreate*RowModel
function.TFeatures
TypeScript Generic:TData
(for row data shape) andTValue
(for column/cell value types).TFeatures
to track registered and loaded_features
in a table instance.TFeatures
generic. TypeScript will warn if you attempt to use a table, row, column, etc., API for an unregistered feature. For example, callingcolumn.pin()
without registeringcolumnPinningFeature
will produce a TypeScript error.ColumnDef
,Column
,Row
,Table
, etc., you should not be affected by these changes.table.getState()
, orcolumn.pin()
). However, due to the new tree-shakable architecture refactor, every API in TanStack Table now has an equivalent static function that can be imported and used. (e.g.table_getState(table)
, orcolumn_pin(column)
). These static functions will be un-memoized variants of the builder pattern APIs that can also be useful for advanced tree-shaking optimizations. Though, due to them being un-memoized, they are not recommended for most use cases, especially in React.New Utilities:
createTableHelper
: Utility for making table factories to share code setup between multiple tables.useTable
method, a easier to usecreateColumnHelper
method that reduces a lot of manual type-safety boilerplate.tableOptions
: Simpler utility for sharing common table options between tables.tableFeatures
: Easier way to make a_features
object with auto-complete/type-safety.Things That Are Staying the Same
table
instance is defined in[create/use]Table
hooks. The render logic remains unchanged, though you may need to adjust APIs if not using certain features. For example, ifcolumnVisibilityFeature
is unregistered, you would replacerow.getVisibleCells
withrow.getAllCells
, as column visibility APIs would be unavailable.Stock Feature Set
Here is the current stock feature list:
columnFacetingFeature
columnFilteringFeature
columnGroupingFeature
columnOrderingFeature
columnPinningFeature
columnResizingFeature
columnSizingFeature
columnVisibilityFeature
globalFacetingFeature
globalFilteringFeature
rowExpandingFeature
rowPaginationFeature
rowPinningFeature
rowSelectionFeature
rowSortingFeature
The V9 refactor split groups of code into different features to be independently imported. Some features that used to be thought of as 1 single feature have been split into multiple features. This is to make it easier to only import the features that you need. For example, column size features have been split into
columnSizingFeature
andcolumnResizingFeature
, so that tables that only need the logic to set initial column sizes can import justcolumnSizingFeature
without importing the logic for users to be able to resize columns. Filtering features were split intocolumnFilteringFeature
,globalFilteringFeature
,columnFacetingFeature
, andglobalFacetingFeature
in a similar way.You will be able to import all of these features independently from each other (for the most part). There are a couple of features that are dependent on each other. For example
globalFilteringFeature
is dependent oncolumnFilteringFeature
, andcolumnResizingFeature
is dependent oncolumnSizingFeature
also being present. This will be made clear in the docs, and we are exploring just adding some type-safe discriminated unions to the_features
object to make it more obvious which features are dependent on each other.Examples
Let's dive into the practical differences between V8 and V9 with some common examples.
Old V8 Example
Here’s an old V8 example for reference that shows off client-side sorting.
Similar V9 Example
Next, let's take a look at what the same example as up above would look like after upgrading to V9. This is a typical upgrade path. Down below, we'll discuss some helper utils to make this code easier to deal with.
Let's discuss what's changed here.
First of all, the resulting bundle size of this new code will be about 6kb in V9 as opposed to about 16kb that it was in V8 (Only considering code from TanStack Table). This small of a difference is not going to change the world, but it's going to make a huge difference in future versions of TanStack Table where we might envision up to 50-100kb of additional features being available from the library.
Code-wise, the most notable change is that any table options that have to do with importing and registering code that is used to create the table instance lives in table options that are prefixed with an underscore. (
_features
and_rowModels
)On the surface, it looks like V9 is getting more complicated than the previous version. This is somewhat true, but it is a tradeoff that we believe will be worth it. We are also introducing some other helper utilities that are discussed down below to make this just about as easy to use as V8.
Outside of how features and row models are defined, very little else is changing. We are not even showing the rendering logic in the above examples since that is expected to largely remain the same. Although you may need to swap which APIs are being called if you no longer wish to use a particular feature. The most common example of this would be swapping
row.getVisibleCells
withrow.getAllCells
if your_features
does not includecolumnVisibilityFeature
.Revamped Helper Utilities
V9 with the New Table Helper Utility
Configuring a TanStack Table
table
instance can be thought of as two main things going on.columns
,data
, and other table option customizationsV9 is introducing a new
createTableHelper
method to make creating multiple tables throughout your code base easier. Use the table helper util to configure features and row models, and other common table options once, then you will be able to create multiple table instances from this table helper.Using the
createTableHelper
will help you only have to think about configuring the_features
and_rowModels
once in your codebase, and then you can create multiple table instances from this table helper.Create Re-usable Table Helper
Here is an example of setting up a table helper that can be re-used throughout your codebase.
Create Table with Table Helper
Now that we have a table helper, we can create multiple table instances from it.
You can continue to just use the standalone
useTable
hook similar to v8, but using atableHelper
can be convenient. By using the table helper here, we were able to clean up a lot of boilerplate code and put it in one place.Table Helper in compliance with React Compiler
What if I Want All Features (Or Don't Care About Bundle Size)
For those who want to upgrade to V9, but want the easiest upgrade path, and also don't care about bundle size, you can copy and paste the following snippet:
This creates a
useReactTable
hook that worked very similarly to V8. All features are included in thestockFeatures
object that you can import from TanStack Table. We're also including the Row Models for whatever client-side features that all of our tables will use.Then you will simply be able to use it throughout your application like so:
New Plugin System
There is a vision that TanStack Table, at its core, it is going to simply be the best starting point and foundation for code organization for building data tables, and that will be its best selling point. The pre-built stock features that come with it are great, but a lot of the value will be in how easy it will be to extend TanStack Table with your own custom niche functionality. My personal goal is to make TanStack Table the easiest library to extend (or override) of just about any other library out there.
Exactly how the plugin system will work with TypeScript is still being optimized. There are 2 approaches that work, and both are better than how it worked in V8. TypeScript performance is the main factor in which approach will be chosen.
In an ideal world, we will make it very easy to extend TanStack Table with custom features for your own custom state, options, and APIs. They will live on the table instance just like any other feature.
Follow along the Custom Features Example to see how it currently works. (This is a work in progress)
Declarations Merging vs No Declarations Merging
Ideally, we don't want to require any declaration merging in order to set up plugins for TanStack Table. TanStack Table V8 currently requires declaration merging to set up plugins.
At the very least, the declaration merging will have 1st class support with dedicated plugin interfaces for you to add your own custom state, options, and APIs to.
Plugins with Declarations Merging
This is already an improvement over V8, but we want to make it even easier to use plugins with TanStack Table. Ideally, you will be able to use plugins on a per-table basis, without affecting the types on other tables in the same project.
Plugins with No Declarations Merging
A proof of concept has been done to allow the types from all features to be registered on the
TableFeature
type. Then theTable
,Column
,Row
,ColumnDef
, etc. types will be able to just pick up the types from every feature and plugin from there. This is way more type-safe and allows for plugins to be used on a per-table basis. However, there are currently some TypeScript performance issues with this approach that still need to be worked out.Conclusions
Let us know what you think of the proposed changes above. We are looking for feedback on the new syntax and code organization.
We have been holding off on alpha releases for a bit, but now that things are starting to stabilize, we will be releasing alphas with all of these breaking changes in the coming weeks. This does not mean that a stable v9 release is right around the corner, but it should be on track for a stable release sometime in 2025.
Looking for Contributions
Want to help TanStack Table V9 ship faster? We are looking for more code contributors! Join the TanStack Table Table-V9 Discord Channel to help get involved.
Here are contributions that could help us speed up the release of TanStack Table V9 by a lot:
Beta Was this translation helpful? Give feedback.
All reactions