
React Table v7 – Hooks for building fast and extendable data grids in React - tannerlinsley
https://github.com/tannerlinsley/react-table/releases/tag/v7.0.0
======
tmpz22
One of the biggest "problems" with React is that it is such an out-of-your-way
ecosystem that teams are able to build their own preferred abstractions
whenever they want. In the mindset of many web developers, we're all geniuses
who surely can invent the more optimal wheel - whether that's because we work
at $BIG_CORP and have the time, or because we work in a start-up like
environment with nobody to audit us and tell us we're collectively acting like
dumb asses.

I've personally wasted several hundred hours this year implementing custom
table logic and design through the react-virtualized-table/react-window
libraries. They are great libraries! But it was not a good use of my time
customizing it into a perfect incantation/API. I over-engineered how the
virtualization tied into our REST API and many of our junior developers
couldn't keep up with the increased abstraction.

Let my story be a lesson that you should probably grab hold of a library like
this, swallow the fact that you're conforming to someone else's API and
concepts, and just get stuff done.

I'll seriously evaluate and likely use this library in future react projects
instead of other more involved implementations. Great docs too!

~~~
nightski
I too have gone down the same road as you. I wish I could share your sentiment
of - just go with React Table.

But React Table is headless. Which is nice, but it's not going to
automatically virtualize rendering. From what I can tell you are going to have
to manually render using react virtualized/window or some other solution to
get that to work. It also doesn't support things like fixed rows or columns
out of the box since it doesn't provide UI.

My initial reaction is that this is a rather complicated API to group, sort,
filter, expand, re-order, and select rows within data structures. It also uses
a lot of prop spreading which is not my favorite.

I'm not sold that you wasted your time. But I'm going to give it a little more
time as my initial assessment could be inaccurate.

~~~
tmpz22
Fair take, but I also believe we should've thrown out virtualization/windowing
entirely. It was of those shiny product-level features that sounds great but
ultimately provides little to no value for _most_ applications.

Most of my point is engineer-oriented but I think it also applies at the
product level. React allows you to build cool features easily - that doesn't
mean every cool idea should be acted upon.

At times this will mean "dumbing-down" design in the name of pragmatism >
shininess. YMMV, ad-supported businesses are going to need that infinite
scroll... but most don't.

~~~
tannerlinsley
Agreed. Most if not all of the production tables I have are using very simple
architecture. Pagination + Data Exploration utilities like
sort/filter/group/etc.

In no way am I preaching that these plugins _should_ used. However, I am proud
that they _can_ be used. And if you end up being one of the users that only
needs a few things to make your production tables great, then you win again by
being able to treeshake out all of the other stuff you choose not to use.

------
Nican
I am trying to load the Examples [1] in CodeSandbox, and I keep getting a
"Request failed with status code 403"

Any idea of what is going on here?

[1] [https://github.com/tannerlinsley/react-
table/blob/master/doc...](https://github.com/tannerlinsley/react-
table/blob/master/docs/examples.md)

~~~
tannerlinsley
Looks like a but with Codesandbox. I believe if you log in, it will bypass
this bug. I'm speaking with CS about it as we speak.

~~~
tannerlinsley
bug _

------
tannerlinsley
At a glance features:

\- Lightweight (5kb - 12kb+ depending on features used and tree-shaking) \-
Headless (100% customizable, Bring-your-own-UI) \- Auto out of the box, fully
controllable API \- Sorting (Multi and Stable) \- Filters \- Pivoting &
Aggregation \- Row Selection \- Row Expansion \- Column Ordering \- Animatable
\- Virtualizable \- Resizable \- Server-side/controlled data/state \-
Extensible via hook-based plugin system

------
dang
Related thread from a few months ago:
[https://news.ycombinator.com/item?id=21630459](https://news.ycombinator.com/item?id=21630459)

------
jannyfer
Just to speak up for those that are struggling with the headlessness of v7...
I have a small team with junior resources that had to build a table in React.

We were hoping for a plug-and-play library, and eventually settled on React
Table v6. Being a small team, I don’t think we’ll migrate over to v7 - we
don’t have any benefits from any more control over the UI than v6 had.

~~~
sgjd
Unrelated but I'm really not a fan of how managers like to dehumanize when
they speak about what are really their colleagues -> You 'have' a team of
'resources'.

Calling them 'reports' is also bad but a least it doesn't sound like something
is going to be used up

------
raarts
Anybody know if it supports GraphQL (with subscriptions)?

~~~
acemarke
It's completely independent of your data sources. You provide the data and
tell it how to set up filtering and sorting and such, it provides the
transformed rows, you render the rows as desired.

------
hpliferaft
Nice!! I use a ton of tables in the react apps I make on the job, so I'm
excited to try this out. Thanks for making it open source.

------
nullorundefined
does it have merged cells? we've had to in-house tables for this alone

~~~
tannerlinsley
A plugin is currently in development to make this extremely easy and turn-key,
but for now (since you control the rendering layer), you can do this on your
own with a few lines of code in your table renderer.

~~~
quink
What I did to merge cells but keep the headers the same was to just suppress
rendering via

    
    
        if (isFakeColumn(cell.column.id)) {
          return <React.Fragment key={cell.column.id}></React.Fragment>;
        }
    

And then render it with another column:

    
    
        {cell.column.id === "title" ? (
          <>
            {cell.render("Cell")}
            <br />
            {row.cells[2].render("Cell")}
            <br />
            {row.cells[3].render("Cell")}
            {" · "}
            {row.cells[4].render("Cell")}
          </>
        ) : (
          cell.render("Cell")
        )}
    

There's probably a way to get at the lot via a string, but by index was quick
and easy enough.

One thing I do have to complain about is the lack of native TypeScript support
- there used to be types in the repo, but they got removed. And
`prepareRow(row)` is a bit ugly, but nothing major and it's only a one-time
call.

~~~
tannerlinsley
Yeah, I'm sorry that's the case now. Having the types as first-class citizens
of the repo while the library was not written in TS or maintained by TS devs
was a big mistake. They are still available (and will updated asap from some
other great devs) in DT. The prepareRow function may be ugly, but not as ugly
as a freakishly slow table with only a handful of rows and columns visible at
once ;)

------
socallo
tannerlinsley for president 2020.

------
oilrefinery
Unfortunately the examples don't seem to work, they return 403 errors.

~~~
tannerlinsley
It's a codesandbox bug. Log in with github for now to bypass the error.

~~~
netsharc
The first thing I looked for was screenshots in the readme. But one has to go
look for it many clicks deep and launch a 3rd party editor (which can be
buggy), and let whatever engine parse and run the code to render the whole
thing, just to see what it looks like.

You have a huge colorful banner at the top of the readme, why not screenshots?

~~~
tannerlinsley
Being a headless table utility, any screenshot of the table UI would either be
over or under selling the potential UI that users will implement with the
library. If you noticed the exmamples are very bare bones styles so as to
highlight the functionality of the library. These examples would be "ugly" as
marketing material. If another example was super dressed up and looked amazing
and used as marketing material, users may be disappointed when they realize
they are in charge of their own styles. It's 6's I believe, so I went with
what I thought was the safest option, exclusion of screenshots.

~~~
netsharc
I suppose then, a screenshot of source code next to the rendered output is
what programmers desire, in the introduction. Instead of thinking "That's a
sexy table!", the programmers will hopefully think "That's some sexy table-
generating code!".

------
pogorniy
While this is a good piece of work I was surprised that it seemed to be
impossible it to control table search and filter from outside of components. I
blame hooks as their behavior seems to be non-trivial to push outside of
component boundaries. Which puts developer in undesirable constraints how to
model application.

~~~
tannerlinsley
You can control the table from wherever you can put the `useTable` hook. 99%
of the time this will be in your table component, but nothing is stopping you
from hoisting this higher or decorating it with whatever other logic you want.
Even if you chose not to hoist the hook, there is also nothing stopping you
from listening to props and using callbacks to update this state. This is not
a constraint of the API and more a constraint of how you choose to model your
component-hook composition points.

~~~
pogorniy
It's one-way control. There is no reasonable way to implement narrative "now
my filter resides in global state. Whenever component changes, it's reflected
in the state. Whenever state changes it's reflected in component". I asked
this question in spectrum community [https://spectrum.chat/react-
table/general/how-to-control-fil...](https://spectrum.chat/react-
table/general/how-to-control-filters-and-other-intended-to-be-local-state-
from-own-state~27f396de-b27c-43ca-ae48-d214509dd028)

~~~
tannerlinsley
There's definitely a difference between taking table state and storing it
somewhere globally for use later and 100% controlling the table state from
outside of the table. Doing the latter involves listening to the table state
for changes in an effect, shipping the new state up to your higher-than-
component storage location, detecting in that same component a change in the
global storage location (usually just a memoized prop or hook of sorts) and
updating the table state with your updated global state using either a table
method like instance.setFilter or even a state reducer if you want _total_
control. The tools are in place and the API is flexible enough to do what you
are referring to. I'm sorry your comment in Spectrum got lost in the noise and
that you had to resort to posting your question on here.

~~~
pogorniy
Thanks for detailed explanation and your time. I do understand that things I
want to achieve are achievable. But I'm not happy with the complexity price I
have to pay.

I believe that moving in the implementation between local and global state
should be a snap. It's a matter of time when need to move local state to
global will arise. And hooks have nothing to propose for that.

Good luck with your project.

~~~
ng12
There's nothing wrong with having useStore() next to useTable() and using a
few effects to keep them in sync.

~~~
pogorniy
This would be acceptableway to go. But I did not manage to get it working. Saw
your comment how to fix, but don't have code to validate that everything would
work as expected.

Thanks.

