Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I AutoScroll with react-sortable-hoc (Table)?

I've been struggling to implement this example noted in the react-sortable-hoc examples page, specifically with the autoscroll behavior within a table. Unfortunately it doesn't look as though source code lives in the examples directory of the repository.

Although the code I've implemented in the codesandbox below is a very simple example, I've been pouring over this for hours, using useWindowAsScrollContainer and getContainer with refs, but nothing seems to resolve the issue.

That said, here's the behavior I'm noting: when scrolling out of the container, and even out of the window, the autoscroll feature never engages. I even resorted to returning document.body with getContainer which should limit the container, but can't seem to replicate the behavior as noted in the repository's example.

Also, although I've specified a fixed height and width on the SortableTable component, ideally this should be wrapped with <AutoSizer />, but removed that for the time being to eliminate any side effects.

https://codesandbox.io/s/mysortabletable-zi94g?file=/MySortableTable.js

  • react-sortable-hoc: 1.11.0
  • react-virtualized: 9.7.5

enter image description here

like image 766
lux Avatar asked May 22 '20 02:05

lux


Video Answer


1 Answers

You need to provider the container to the Sortable component to which it must restrict the sortableElement when using 3rd party libraries for rendering using the getContainer prop.

As per the react-sortable-hoc documentation:

getContainer is an Optional function to return the scrollable container element. This property defaults to the SortableContainer element itself or (if useWindowAsScrollContainer is true) the window. Use this function to specify a custom container object (eg this is useful for integrating with certain 3rd party components such as FlexTable). This function is passed a single parameter (the wrappedInstance React element) and it is expected to return a DOM element.

Now since you cannot pass a direct ref to the child, you can write a small wrapper over the Table component before passing it to the HOC

const MyTable = ({ tableRef, ...rest }) => {
    return <Table ref={this.props.tableRef} {...rest} />;
}
const SortableTable = SortableContainer(MyTable);
const SortableTableRowRenderer = SortableElement(defaultTableRowRenderer);

/**
 * Define the table schema
 */
const schema = [
  { dataKey: "col1", label: "Column 1" },
  { dataKey: "col2", label: "Column 2" }
];

/**
 * Generate row data according to the schema above
 * @param {*} rowCount
 */
function generateRows(rowCount) {
  const rows = [];
  for (let i = 0; i < rowCount; i++) {
    rows.push({ col1: i, col2: i * i });
  }
  return rows;
}

class MySortableTable extends Component {
  state = {
    schema,
    rows: generateRows(200)
  };

  onSortEnd = ({ oldIndex, newIndex }) => {
    this.setState(({ rows }) => ({
      rows: arrayMove(rows, oldIndex, newIndex)
    }));
  };

  rowRenderer = props => {
    return <SortableTableRowRenderer {...props} />;
  };

  getRow = ({ index }) => {
    const { rows } = this.state;
    return rows[index];
  };

  render() {
    const { rows, schema } = this.state;

    return (
      <SortableTable
        width={500}
        height={500}
        headerHeight={32}
        rowHeight={32}
        tableRef={ref => (this.tableRef = ref)}
        getContainer={() => ReactDOM.findDOMNode(this.tableRef.Grid)}
        rowCount={rows.length}
        rowGetter={this.getRow}
        onSortEnd={this.onSortEnd}
        rowRenderer={this.rowRenderer}
      >
        {schema.map(col => (
          <Column {...col} key={col.dataKey} width={100} />
        ))}
      </SortableTable>
    );
  }
}

Working demo

like image 113
Shubham Khatri Avatar answered Sep 30 '22 15:09

Shubham Khatri