question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Using html table element

See original GitHub issue

Do you have an example of using this with tables? I’m trying to get it working but I have a strong suspicion that it either doesn’t work, or that I’m doing something very wrong. I’ve set the outerTagName to “table” and the innerTagName to “tbody”, but I don’t get any scrolling.

Here is my code, not sure if it helps (items is a list of objects):

 <List
            outerRef={this._list}
            outerTagName="table"
            innerTagName="tbody"
            height={300}
            itemData={items}
            itemSize={() => 30}
            itemCount={items.length}
            itemKey={item => item.uniqueId}>
            {({index, style, data}) => {
              return (
                <tr style={style} key={index}>
                  <td>Item {index}</td>
                </tr>
              );
            }}
          </List>

Issue Analytics

  • State:closed
  • Created 5 years ago
  • Reactions:4
  • Comments:38 (7 by maintainers)

github_iconTop GitHub Comments

52reactions
jamesmfriedmancommented, Feb 19, 2020

@pupudu I applaud your open source efforts and looked through your code extensively before deciding to try to tackle this on my own. I just wanted the super straightforward thing other people were looking for: this library but with table elements.

Turns out I was able to pull this off with a very small bit of code, and a lot of creativity. The code is simple enough that anyone should be able to copy / paste and extend to their liking. @bvaughn after figuring out the how, this would be pretty trivial to add to the library if you want, but also pretty trivial to override if you know how.

The short of it:

  • Capture the “top” style of the first row after a render
  • Store that value in React.Context so we can pass it around
  • Apply the value to a table component which will be what gets moved around, instead of the rows themselves
  • Add additional slots for things like headers and footers.
  • The ergonomics of the library don’t allow things to be passed around neatly, so React.Context is the hero to overcome the cross component communication.

Working Code Sandbox: https://codesandbox.io/s/react-window-with-table-elements-d861o

Code for reference

import React from 'react'
import { useState, useRef, useContext } from 'react'
import { FixedSizeList, FixedSizeListProps } from 'react-window'
import { render } from 'react-dom'

/** Context for cross component communication */
const VirtualTableContext = React.createContext<{
  top: number
  setTop: (top: number) => void
  header: React.ReactNode
  footer: React.ReactNode
}>({
  top: 0,
  setTop: (value: number) => {},
  header: <></>,
  footer: <></>,
})

/** The virtual table. It basically accepts all of the same params as the original FixedSizeList.*/
function VirtualTable({
  row,
  header,
  footer,
  ...rest
}: {
  header?: React.ReactNode
  footer?: React.ReactNode
  row: FixedSizeListProps['children']
} & Omit<FixedSizeListProps, 'children' | 'innerElementType'>) {
  const listRef = useRef<FixedSizeList | null>()
  const [top, setTop] = useState(0)

  return (
    <VirtualTableContext.Provider value={{ top, setTop, header, footer }}>
      <FixedSizeList
        {...rest}
        innerElementType={Inner}
        onItemsRendered={props => {
          const style =
            listRef.current &&
            // @ts-ignore private method access
            listRef.current._getItemStyle(props.overscanStartIndex)
          setTop((style && style.top) || 0)

          // Call the original callback
          rest.onItemsRendered && rest.onItemsRendered(props)
        }}
        ref={el => (listRef.current = el)}
      >
        {row}
      </FixedSizeList>
    </VirtualTableContext.Provider>
  )
}

/** The Row component. This should be a table row, and noted that we don't use the style that regular `react-window` examples pass in.*/
function Row({ index }: { index: number }) {
  return (
    <tr>
      {/** Make sure your table rows are the same height as what you passed into the list... */}
      <td style={{ height: '36px' }}>Row {index}</td>
      <td>Col 2</td>
      <td>Col 3</td>
      <td>Col 4</td>
    </tr>
  )
}

/**
 * The Inner component of the virtual list. This is the "Magic".
 * Capture what would have been the top elements position and apply it to the table.
 * Other than that, render an optional header and footer.
 **/
const Inner = React.forwardRef<HTMLDivElement, React.HTMLProps<HTMLDivElement>>(
  function Inner({ children, ...rest }, ref) {
    const { header, footer, top } = useContext(VirtualTableContext)
    return (
      <div {...rest} ref={ref}>
        <table style={{ top, position: 'absolute', width: '100%' }}>
          {header}
          <tbody>{children}</tbody>
          {footer}
        </table>
      </div>
    )
  }
)

/**
 * Render Our Example
 **/
render(
  <VirtualTable
    height={300}
    width="100%"
    itemCount={1000}
    itemSize={36}
    header={
      <thead>
        <tr>
          <th>Index</th>
          <th>Header 2</th>
          <th>Header 3</th>
          <th>Header 4</th>
        </tr>
      </thead>
    }
    row={Row}
    footer={
      <tfoot>
        <tr>
          <td>Footer 1</td>
          <td>Footer 2</td>
          <td>Footer 3</td>
          <td>Footer 4</td>
        </tr>
      </tfoot>
    }
  />,
  document.querySelector('main')
)

11reactions
ThiefMastercommented, Jul 2, 2020

IE11 is not something you should be supporting anymore 😃

Read more comments on GitHub >

github_iconTop Results From Across the Web

<table>: The Table element - HTML - MDN Web Docs - Mozilla
The <table> HTML element represents tabular data — that is, information presented in a two-dimensional table comprised of rows and columns ...
Read more >
HTML Tables - W3Schools
A table in HTML consists of table cells inside rows and columns. ... Note: A table cell can contain all sorts of HTML...
Read more >
How to use the 'table' element in HTML - Educative.io
An HTML table element consists of some tags and attributes necessary to build a table. Those tags are as follows: ... The <table>,...
Read more >
HTML Table - Javatpoint
HTML table tag is used to display data in tabular form (row * column). There can be many columns in a row. We...
Read more >
HTML - Tables - Tutorialspoint
Table heading can be defined using <th> tag. This tag will be put to replace <td> tag, which is used to represent actual...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found