0

Variations of this question has been asked at least a couple of times before. For example:

React component in a Tabulator custom formatter and

Properly display React component in react-tabulator column

Apologies for posting a similar question, but I have additional questions to ask.

For illustrative purposes, my React component is simple and looks like this:

type ReactThingProps = {
  chldren: any;
  colour: string;
};

const ReactThing: React.FunctionComponent<ReactThingProps> = ({
  colour,
  children,
}: ReactThingProps) => {
  return <span style={{ backgroundColor: colour }}>{children}</span>;
};

export default ReactThing;

My React based formatter currently looks like this:

const ReactFormatter = (
  cell: any,
  _formatterParams: object,
  _onRendered: EmptyCallback
) => {
  const reactNode = document.createElement("span");
  const reactRoot = createRoot(reactNode);
  reactRoot.render(
    <ReactThing colour={cell.getValue()}>{cell.getValue()}</ReactThing>
  );
  return reactNode;
};

And I hook it up like any other formatter, in the column definition:

{ title: "Despised Color", field: "despCol", formatter: ReactFormatter },

While what I have "works", I feel it is far from optimal.

Problem #1: I'm creating a root in every cell of the column, and rendering react into it. I think I should be calling unmount on reactRoot, as I think cells could get destroyed as a result of the grid's virtual dom. Question: What event could I hook into to clean up my react root code?

Problem #2: Assuming I can clean up the dom node successfully, it feels like it's probably a lot of overhead in creating the root, rendering to it, and tearing it down when the cell is about to get destroyed. Question: Is there a less naive way to introduce React components into a custom formatter (or some other extension point)?

Notre
  • 1,093
  • 3
  • 13
  • 26
  • What you are experiencing is the fundamental limitations of introducing React into non-react code. Why not replace the whole table with a react library like react table? – adsy Jun 15 '23 at 20:18
  • Thanks @adsy. Going with an react-first table like react-data-grid or a headless solution like tanstack table is certainly a possibility, and maybe the best option. I'd like to explore what options there are (if any) before giving up on a vanilla javascript library like Tabulator – Notre Jun 15 '23 at 20:25
  • Generally React tends to end up eating your whole codebase. What you have isn't bad BTW, but only if integrating existing legacy code with a react component. If your coming at it fresh, its a bad idea to adopt a non-react API for the reasons you mention. – adsy Jun 15 '23 at 20:30
  • You're right though. When the cell unmounts, you really wanna run `unmountComponentAtNode` but to do so easily the library would need some event that indicates a cell is being removed, and I'm not sure it does after a brief look. It's a memory leak otherwise. There isn't really a way to do this other than manually managing the mounts and unmounts -- which is tiresome when done from the "outside". – adsy Jun 15 '23 at 20:34
  • If you really wanted this and for it to be more scalable, you could register a mutation observer to detect when the cell is removed and call `unmountComponentAtNode` but the observer itself is a resource hog in and of itself (relatively obviously, its tiny on the grand scale of things). – adsy Jun 15 '23 at 20:37
  • Thanks for taking the time to comment, @adsy. I think you're likely right. Are you a contributor to tabulator? Just wondering if it easy for someone to add an event to tabulator, if one doesn't exist (I couldn't find one either from the docs). The mutation observer is interesting, but I'm wondering if Tabulator recycles DOM nodes, rather than actually destroying and recreating. I think (not positive) maybe some other grids may do this – Notre Jun 15 '23 at 20:47

0 Answers0