Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactor reactFormatter to use createRoot for React 18 compatibility #287

Open
wants to merge 2 commits into
base: master
Choose a base branch
from

Conversation

aleruizj
Copy link

@aleruizj aleruizj commented Dec 8, 2023

This update modifies the reactFormatter utility to use the createRoot function from 'react-dom/client', ensuring compatibility with React 18's new rendering API. It addresses the warning about ReactDOM.render being deprecated in the new version of React.

By wrapping the JSX element with createRoot, we're able to mount React components within Tabulator's custom formatter without relying on the outdated ReactDOM.render method. This change adheres to the best practices recommended by the React 18 upgrade strategy.

This update modifies the reactFormatter utility to use the createRoot function from 'react-dom/client', ensuring compatibility with React 18's new rendering API. It addresses the warning about ReactDOM.render being deprecated in the new version of React.

By wrapping the JSX element with createRoot, we're able to mount React components within Tabulator's custom formatter without relying on the outdated ReactDOM.render method. This change adheres to the best practices recommended by the React 18 upgrade strategy.
@HolyArseny
Copy link

@aleruizj Nice work, but I see a mistake in your code. There is no props passing from tabulator to JSX element.

@hsn93
Copy link

hsn93 commented Feb 17, 2024

i dont see why
return "<div class='formatterCell'></div>"; when you only do cell.getElement().

also you could pass the props just like before. so that you dont break compatiblity.

also notice that there is row height issue with this code (not related to your change specifically but how react and tabulator renderer stuff work i guess)

attached screenshot:
before using render():
image

after using root.render():
image

i dont have experience with react i dont know why :)

best result i came up with (that works on my application) was this: (i dont like how to code looks, specially that setTimeout(10mS))

const rootMap = new Map<HTMLElement, Root>();

export function reactFormatterNew(JSX: any) {
  return function customFormatter(
    cell: Tabulator.CellComponent,
    formatterParams: any,
    onRendered: (callback: () => void) => void
  ) {
    const renderFn = () => {
      const cellEl = cell.getElement();
      const existingRoot = rootMap.get(cellEl);
      const CompWithProps = React.cloneElement(JSX, { cell });

      if (existingRoot) {
        existingRoot.render(CompWithProps);

        cell.getRow().normalizeHeight();
      } else if (cellEl) {
        const formatterCell = cellEl.querySelector('.formatterCell');
        if (formatterCell) {
          const root = createRoot(cellEl);
          rootMap.set(cellEl, root);
          root.render(CompWithProps);

          cell.getRow().normalizeHeight();
        }
      }
    };

    onRendered(renderFn);

    setTimeout(() => {
      renderFn();
    }, 10);

    return '<div class="formatterCell"></div>';
  };
}

update: i had to register table.on('rowUpdated', r => r.normalizeHeight()) on my application to make rows update their height.

however, the solution has flaws. tabulator would delete rows and cells, this is not friendly with react 18 as it expects user to call root.unmount(). i tried to register callback ('rowDelete') but it did not work for me. so i downgraded my app to react 17

@dtoxvanilla1991
Copy link

Any movement on this?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

4 participants