Rohit Kalkur

 

rovolution

@Rovolutionary

Software Engineer

@

Problem

  • Social Table's Event Dashboard is the first view customers see after logging in 
  • Old dashboard was legacy code built with Knockout.js / jQuery
  • No pagination (all data rows created in DOM)

What Did We Want?

  • Pagination
  • Minimal amount of nodes in the DOM
  • Filtering
  • A clean, sensible code architecture
  • A better design wouldn't hurt either!

Fixed Data Table!

  • FixedDataTable can be used to show our list of events
  • Consists of 3 types of components
    • Table
    • Column
    • ColumnGroup

Fixed Data Table!

  • Can be customized via props (which are well documented)
  • Takes props for literally anything and everything
    • width (required)
    • height (required)
    • rowsCount (required) 
    • column content
    • scroll position

Fixed Data Table!

  • The most important prop is rowGetter
  • This is used by the component to retrieve the data at a given row
  • dataKey property of Column is used to access the data for the cell from the row

Fixed Data Table!

data

 

       {
          "id": 0,
          "name": "Bob",
          "age": 10
       }


       {
           "id": 1,
           "name": "Jane",
           "age": 20
        }

 

 <Table
    rowHeight={50}
    rowGetter={rowGetter}
    rowsCount={data.length}
    width={5000}
    height={5000}>
    <Column
      label="Name"
      width={3000}
      dataKey={'name'}>
    <Column
      label="Age"
      width={3000}
      dataKey={'age'}>
</Table>

Name

Age

Bob

Jane

10

20

function rowGetter(rowIndex) {
    return data[rowIndex];
}

Fixed Data Table!

  • Easy to see how this works for static data set, but what about dynamic data (for ex: pagination) ?
  • FixedDataTable examples all use custom data stores for handling data fetching logic

EventsStore

  • Holds the list of events that the events table uses
  • FixedDataTable's rowGetter prop is set to a method implemented directly on the store. For ex.
    • rowGetter = EventsStore.getEventAt
  • User actions trigger methods on the store
    • EventsStore.fetch()
    • EventsStore.delete()

EventsStore

  • EventStore is also an event emitter
  • Whenever store's contents are updated via fetch(), delete(eventId), etc..., it updates its data and triggers an 'update' event
  • events-table component is subscribed to 'update' event, and when an update occurs, it calls setState() and updates its events state data.

Code Architecture

EventsStore.js

 

events-table.jsx

 

'update'

EventsStore.fetch()

_updateEvents: function() {

     this.setState({

         events: EventsStore.getEvents()

     });

}

componentWillMount: function() {

   EventsStore.on('update', this._updateEvents);

}

EventsStore

  • But what about pagination???
  • Pagination logic can be also be handled by the store as well!
  • For instance, let us say our user has 600 events, and we have a page size of 200
  • Pass 600 in for the rowCount prop for Table.
  • When getEventAt() is called via rowGetter, you can create whatever custom page retrieval logic you want!

EventsStore

  • For example, if getEventAt() has been called for 75% of the data on the current page, then go ahead and optimistically fetch the next page!

EventsStore

  • All data fetching/pagination logic happens in the store itself
  • Stores become highly logical
  • Facebook realized that people were implementing certain logic patterns repeatedly in stores (such as pagination), and created abstractions for these in their Relay framework

Conclusion

  • FixedDataTable is an awesome component for creating customizable data tables in React
  • Creating a separate data store for handling the data allows you to cleanly decouple data fetching/manipulation logic from display and leads to more understandable code!
  • Griddle is a fixed data table alternative that is more fully featured
Made with Slides.com