Skip to main content

Welcome

TLDR

  • ReactDataGrid is a React component for displaying tabular data, built from the ground up for 2023, by a team with 20+ years of experience building datagrids.
  • It integrates deeply with Material UI, but thanks to its highly customizable rendering engine, it can be used with any UI framework, or without any UI framework at all. If you are already using Material UI, this datagrid will seamlessly integrate with your application in terms of user experience, theming, and customization.
  • It is very light weight without compromising on features, thanks to a combination of thoughtful design, modern tooling & ecosystem, plugin architecture, and ES6 modules. More on this below.
  • Built in React for React, with TypeScript.

What is ezgrid ReactDataGrid?

ezgrid (Enterprise User eXperience Data Toolkit) is a toolkit for visualizing data in enterprise applications. The primary component in this library is a ReactDataGrid that can be used to display data in a tabular or hierarchical format.

A Trip down the memory lane

Depending on when you began your journey with us, you are using one of our many different DataGrid components (Or are completely unfamiliar with us , in which case, welcome!). Our DataGrid history starts way back in the early 2000's. We built what was the single most popular DataGrid component in the world for Flex and Flash (for those of you who remember what that even is!), used by tens of thousands of developers worldwide including more than 50% of the Fortune 500 companies. And then came the infamous Steve Jobs Flash killer letter. We saw the writing on the wall and began porting our datagrid to HTML - with jQuery, and then to Android and to iOS and then to react back in 2017, and now again in 2023! These are only the published products. In house, we have one for angular, vue, web components, and others. In addition to offering off the shelf datagrid products, we have built extensions and custom features for hundreds if not thousands of customers over the years.

Needless to say, we're more than a little familiar with datagrids, and the universe of functionality that can be built around them. So, with that said, why did we choose to write a new react datagrid? Well, our older products (both the react one and the pure html one), like most commercial datagrid components - were written in 2010s. And the JavaScript ecosystem of 2023 is very very different than the JavaScript ecosystem of 2010s. React of 2016/17 vs React of today is a whole different platform as well. We've learned a lot over the years, and we've seen a lot of things that we would do differently if we were to start from scratch today. What follows is a technical deep dive into the design decisions that went into building this component. It might be helpful for JavaScript/TypeScript developers even if you are not using our component.

Material UI (And others)

If you are using React, there is a good chance you are using MUI. When we wrote this product, integration with MUI was among the most important success criteria. As you can see in the demos, as soon as you plug in the Material Adapter, all of the primitives - icon buttons, checkboxes, text fields, dropdowns, date pickers, everything switches over to the adapter's rendering. An added benefit of this is, all the Material styling, accessability and theming features are automatically available to the grid, as you can see from the material examples. The filters, editors, toolbar actions, are all MUI components, and the grid knows how to integrate with them. This is what we mean by first class integration with MUI. As of this writing, adapters for Bootstrap, Ant Design, and Chakra are in the works. Please let us know if you would like to see an adapter for a specific framework.

However, we wanted to ensure that you don't have to use MUI or any other library to use our product. In our entire spirit of keeping our package size small and dependency free, we architected the grid to be extremely pluggable. The grid is a tree of nodes, and every node returns a React Element. The grid does not really care what that react element is, just needs a react element. It could be a Material UI element, or a Bootstrap element, or a simple DIV. A natural consequence of this approach was a highly customizable rendering engine. If you look at our MUI adapter, its barely a couple hundred lines of code, most of which is just which icons to use where. This speaks to how easy it is to radically customize the look and feel of the grid.

Bundle Size

DataGrids are complex components. They are not just a table. They have a lot of functionality, and a lot of code. Many commercial DataGrids, ours included, have built up a ton of legacy bloat. This is not a bad thing. It is a natural consequence of building a product over a long period of time. However, it does mean that the codebase is not as lean as it could be. We've found ourselves in this situation - in order to meet customer needs, anytime we get a feature request, we've tried to add it to the core product. What we've realized over the years is that this code is being used by a very small percentage of our customers. Today, if you were to use any of the commercial datagrids (our older products included), you would be adding 500K-1MB or more to your bundle. This is a lot of code, and it increases the payload and memory footprint of your application. It increases the amount of time it takes for your app to compile, which increases the iterative code/test cycle for your developers, hinders HMR (Hot module reload), and makes developers less productive. A lot of older components are built in a way that does not allow for tree shaking. One way to check to see if your current library is using treeshaking is to look at the package.json and check to see if sideEffects is false. Our product, comes in a tiny 190KB, side-effect free package. If you don't use all the features, it is < 100K because of the tree shaking (discussed below). This is literally a fraction of our older products and most other commercial grids, without compromising on features. You can also spin up a simple react application and import our grid and compare it to the size of the final bundle, and you will see how much little this library will add to your application.

Evolution of Webpack, Tree Shaking, and ES6 Modules

Most of you are already familiar with WebPack and all its magic. Similar bundlers like Vite, Rollup, Parcel, etc. are also gaining a lot of traction. All of these support Tree Shaking, which is the process of removing unused code from your bundle. This is a very important feature, because it allows you to only include the code that you need in your bundle, thereby reducing the memory as well as the payload footprint of your application. Unfortunately, there are some very specific nuances that have a dramatic impact on how treeshaking works. First, for tree shaking to work at its best, you need to use es modules, and us as library authors need to build libraries that export them correctly. CommonJS, which is the more prevalent library format as of today, does not tree-shake well. Second, as library authors, we need to ensure our code is sideEffect free. This is absolutely critical. Even today, many libraries, including major commercial options are not sideEffect free. Third, classes and OOP in JavaScript does not tree shake well. They are useful in many cases, but they are not ideal for tree shaking in terms of writing "sideEffect" free code. By reorganizing a majority of our code into idempotent functions, having related chunks of functionality coalesce into a single module "behaviors", that can be plugged in at runtime instead of being baked into the bundle at compile time, we were able to achieve much better tree shaking results. All of these changes required us to fundamentally rethink how we write our code, and how we organize it, which is why we chose to write a new component from scratch, while still leveraging the core of our existing codebase.

Inception : The DataGrid Edition

If you haven't seen the movie, apologies :-). If you have, then the analogy will make sense. We used the grid to implement the features of the grid! The settings popup that lets you control column visibility? Its a hierarchical DataGrid component. The Manage Settings popup that allows you to switch between views? Yep. Another DataGrid. The multi select and date dropdown filters? you guessed it, a DataGrid inside a dropdown. The Filter Builder? A DataGrid! This embedding of the grid inside a grid has helped us reduce our code footprint, and also allowed us to build a lot of functionality in a very short amount of time. Finally, So much of the code inside grid-core is recursive. Its functions calling themselves - because end of the day its a component tree. A tree of virtual nodes that translates to the React VDOM, that translates to the browser DOM. Trees and recursion are like peas in a pod. Conceptually, so much of what we're doing in code feels the same way. Rows are hierarchical, but so are columns. With small reusable idempotent functions, we've tried to keep our code as concise as possible. And the results speak for themselves. The grid has most of the heavily used features of our older products, but with a much smaller footprint.

TypeScript

If you are already using Typescript, you can skip this section. If you are still using, JavaScript, read on! For those of you who remember Flash/Flex and action-script compared to the jungle that used to be JavaScript of the day, you'll understand why we chose TypeScript. If you are not familiar with TypeScript, it is a superset of JavaScript that adds static typing, interfaces, enums, generics, and other features that make it easier to write large scale applications. It is a language that compiles to JavaScript, and is a first class citizen in the JavaScript ecosystem. It is also a language that is gaining a lot of traction in the industry, and is used by many large companies. Although its not required to use TypeScript to use our component, we highly recommend it.

Internet Explorer (RIP)

We chose to dedicate a separate section for IE in this document. IE finally rode off into the sunset June 15, 2022. This culminates over a decade of pain and suffering and frustration and if(IE) statements littered all over our code. As JavaScript developers, we've all suffered through this. And because our single package needed to work regardless of browser, all these if(IE) statements got built into your bundle. And as component developers, we had to support IE until the very end. No more! It feels so liberating to write this! Compared to our older products, we've almost eliminated browser specific code. This is a huge win for our customers, and for us. Modern cross browser support for features we had to write (like drag and drop, HTML 5 native date pickers, flex-box) etc that weren't well universally supported until recently, has eliminated the need for thousands of lines of code we had in our older codebase.

Pluggability over Configuration

A common complaint we got over our older products was that although it was extremely powerful, it had way too many properties. We let you customize a million things using boolean/numeric flags. And no matter how many flags we provided, we ALWAYS had requirements from customers that made us go "just use the renderer". These flags led to confusion, bugs, and in general a poor developer experience because as the number of flags increased, the combinations increase exponentially, and it becomes impossible to test all the combinations. We decided to take a different approach this time around. We decided to make the grid as pluggable as possible. As an example, instead of giving you a dozen flags for verticalGridLines, verticalGridLineThickness, verticalGridLineColor, repeated at each nested levels (because they can be different), we just say - use custom css for global changes, and if not, use cellStyleFunction. Same effect, but much more powerful. We also made it incredibly easy to inject renderers, features and behaviors. We made pluggability a cornerstone of the design, and we used it ourselves extensively through out the core. For example, we used it to completely replace the rendering engine to use Material UI primitives in the adapter. And since the gridOptions is just an object, you can have a global config object that you destructure in all your configs. We actually do this in our own code, because (as we talked about in the Grid Inception section), we use the grid to implement the grid. So we have a global config object that we destructure in all our configs. This has made our codebase much more concise, and easier to maintain. This is how, when you plugin for example the material adapter in the main grid, all inner grids automatically inherit it.

Features

While our grid supports a vast array of features out of the box, one of core design decisions was to make it very easy to customize the product. If you are a source customer, you will see our product has 3 libraries internally. Grid Core is a 0 dependency pure logic library. Does not even need react. It takes your data, and converts it into a large tree of nodes. Then there is Grid-React. This knows how to take these nodes, and convert them to React Elements. The only dependency here is react (version 16 or above). Finally, there is the grid-export. Where the only dependencies are jsPdf, excel-js, or whatever export library you choose. The demos also show how to plug in Material into grid-react, so you can completely swap out the grids built in primitives with Material components which goes to tell you how easy it is to customize our product. The grid core/react, comes in a tiny 190KB, side-effect free package. If you don't use all the features, it is < 100K because of the tree shaking mentioned above. This is literally 1/5th of our older products (and many other commercial ones as well).

One of our most prominent strength is our first class support for hierarchical/tree shaped data. We like to believe all data is essentially hierarchical. This is because data is nothing without relationships. We've built our component to support this. While most other grid components will show a simple master/detail or expand/collapse type rows, we've taken it many steps further, and integrated hierarchical filtering, floating rows that give your users context while scrolling, lazy loading at all levels, virtualized scrolling of hierarchical data, Selection Cascade, Group Headers, Very Large Hierarchical Grids, Inner Level Renderers with Locked Column Support and many more features built around this. Its very easy to write features with for flat data. Once you add an additional depth dimension, which is the case with most real world data, things get a lot more complicated. Support for complex hierarchical data has been a cornerstone of our products for over two decades, and we've carried on that DNA into this component.

Legacy

We've been writing DataGrids for almost 2 decades now. We've written them in Flash, Flex, jQuery, DOJO, EXTjs, Angular, React, Vue, WebComponents, Android, iOS and this is our latest edition. We've learned a lot over the years, taken things that we would do differently if we were to start from scratch today, kept the things we got right, and distilled it into this component. While nothing is perfect, this product is the culmination of all our experience, and we are very proud of it. We hope you enjoy using it as much as we enjoyed building it.