Refactor reactFormatter to use createRoot for React 18 compatibility
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.
@aleruizj Nice work, but I see a mistake in your code. There is no props passing from tabulator to JSX element.
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():
after using root.render():
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
Any movement on this?