schrodinger/fixed-data-table-2

Support forwarding refs to cell components, allowing access to the DOM element rendered by the cell.

gersongoulart opened this issue · 3 comments

Current Behavior

Currently, to grab a hold of a table cell DOM element, developers must use React.findDOMNode to find the browser DOM node for a React class component instance. This API is deprecated and will be removed in a future major version of React. See the alternatives.

Expected Behavior

Developers should be able to pass a ref to the DataCell (FixedDataTableCellDefault) component, enabling external access to the underlying DOM element of the cell.

By forwarding the ref, you can now perform operations such as focusing the cell, measuring its dimensions, or integrating it with other libraries that require direct DOM interaction. To use this feature, we would simply pass a ref prop to the DataCell component, and it will be attached to the top-level div element rendered by the cell. This enhancement provides greater flexibility and control when working with table cells in the application without relying on deprecated APIs.

Example usage:

import { DataCell } from 'fixed-data-table-2';

export function EditableCell(props) {
  const { viewComponent: View, editComponent: Edit, ...cellProps } = props;
  const cellElement = useRef(null);
  const view = useViewCell(cellProps);
  const edit = useEditCell(cellProps);
  const Component = edit.isEditing ? Edit : View;

  return (
    <DataCell
      ref={cellElement} // this will save a reference to the underlying DOM node...
      onClick={edit.onEdit}
      >
      <Component
        {...cellProps}
        {...view}
        {...edit}
        cellElement={cellElement} // ...which can now be used by other components for interaction.
      />
    </DataCell>
  );
}

Possible Solution

Since this project is on React v17+, the simplest way to accomplish this, is to convert the (FixedDataTableCellDefault) component to a function-style component with forwardRef.

Example:

const FixedDataTableCellDefault = React.forwardRef(function FixedDataTableCellDefault(props, ref) {
  // Same code as before.
});

FixedDataTableCellDefault.propTypes = {/* propTypes gotta live out here */}

export default FixedDataTableCellDefault;

Context

As I work to upgrade my project's codebase in preparation for React v19, I am attempting to resolve all issues that could prevent the upgrade, and the reliance on React.findDOMNode is one of them.

@gersongoulart , the proposed solution sounds reasonable to me.
Feel free to put in a PR for this.

Fixed with v2.0.13 via #727.

Client's can now pass ref to the DataCell renderer to grab the top-level DOM node.
eg:

import { DataCell } from 'fixed-data-table-2';

export function CustomCell(props) {
  const cellElement = useRef(null);

  return (
    <DataCell
      {...props}
      ref={cellElement} // this will grab a reference to the underlying DOM node...
    >
      <CustomComponent
        {...props}
        cellElement={cellElement} // ...which can now be used by other components for interaction.
      />
    </DataCell>
  );
}

@gersongoulart, I'm closing this thread since the issue is resolved, but feel free to comment if we missed anything.

And good luck with the React v19 upgrade. Let us know if you face any blockers.