Skip to content

Commit fb6c370

Browse files
Allow ReorderCell to work in React v19 (#745)
The `<ReorderCell />` plugin component doesn't work correctly in React v19. This is because it uses the `ReactDOM.render` API which is removed in React v19. ## Fix I'm adding in a new prop named `__react19RootCreator` which allows users to pass in the `createRoot` API so that `<ReorderCell />` works as expected. The prop is already marked as deprecated in the docs, and prefixed with`__` to make it apparent that this is more of a hack/temporary workaround. We'll remove it in FDT v3 since we'll probably only support React 18 and above. Example usage: ```tsx import { createRoot } from 'react-dom/client'; ... const reorderCell = ( <Plugins.ReorderCell __react19RootCreator={createRoot} > {cellContents} </Plugins.ReorderCell> ) ```
1 parent 84e2d3f commit fb6c370

File tree

1 file changed

+46
-6
lines changed

1 file changed

+46
-6
lines changed

src/plugins/ResizeReorder/ReorderCell.js

+46-6
Original file line numberDiff line numberDiff line change
@@ -240,13 +240,30 @@ class ReorderCell extends React.PureComponent {
240240
contents: this.cellRef.current,
241241
};
242242

243-
ReactDOM.render(
244-
// Since we're effectively rendering the proxy in a separate VDOM root, we cannot directly pass in our context.
245-
// To solve this, we use ExternalContextProvider to pass down the context value.
246-
// ExternalContextProvider also ensures that even if our cell gets unmounted, the dragged cell still receives updates from context.
243+
// Since we're effectively rendering the proxy in a separate VDOM root, we cannot directly pass in our context.
244+
// To solve this, we use ExternalContextProvider to pass down the context value.
245+
// ExternalContextProvider also ensures that even if our cell gets unmounted, the dragged cell still receives updates from context.
246+
const proxy = (
247247
<ExternalContextProvider value={this.context}>
248248
<DragProxy {...this.props} {...additionalProps} />
249-
</ExternalContextProvider>,
249+
</ExternalContextProvider>
250+
);
251+
252+
if (this.props.__react19RootCreator) {
253+
const flushSync = ReactDOM.flushSync || ((fn) => fn()); // ReactDOM.flushSync doesn't exist in older versions of React
254+
// flushSync is required to ensure that the drag proxy gets mounted synchronously in newer version of React
255+
flushSync(() => {
256+
const root = this.props.__react19RootCreator(this.getDragContainer());
257+
this.dragContainer.root = root;
258+
root.render(proxy);
259+
});
260+
// we consider our cell to be in a reordering state as soon as the drag proxy gets mounted
261+
this.setState({ isReordering: true });
262+
return;
263+
}
264+
265+
ReactDOM.render(
266+
proxy,
250267
this.getDragContainer(),
251268
// we consider our cell in a reordering state as soon as the drag proxy gets mounted
252269
() => this.setState({ isReordering: true })
@@ -287,7 +304,11 @@ class ReorderCell extends React.PureComponent {
287304

288305
removeDragContainer = () => {
289306
// since the drag container is going to be removed, also unmount the drag proxy
290-
ReactDOM.unmountComponentAtNode(this.dragContainer);
307+
if (this.props.__react19RootCreator) {
308+
this.dragContainer.root.unmount();
309+
} else {
310+
ReactDOM.unmountComponentAtNode(this.dragContainer);
311+
}
291312

292313
this.dragContainer.remove();
293314
this.dragContainer = null;
@@ -363,6 +384,25 @@ ReorderCell.propTypes = {
363384
* ```
364385
*/
365386
onColumnReorderEnd: PropTypes.func.isRequired,
387+
388+
/**
389+
* HACK to make this plugin work in a React v19 environment by letting the client pass the `createRoot` function from `react-dom/client`.
390+
*
391+
* Example usage:
392+
* ```
393+
* import { createRoot } from 'react-dom/client';
394+
*
395+
* const reorderCell = (
396+
* <ReorderCell
397+
* __react19RootCreator={createRoot}
398+
* />
399+
* ```
400+
*
401+
* See https://github.com/schrodinger/fixed-data-table-2/issues/743) for more information.
402+
*
403+
* @deprecated This'll be removed in future major version updates of FDT.
404+
*/
405+
__react19RootCreator: PropTypes.func,
366406
};
367407

368408
export default ReorderCell;

0 commit comments

Comments
 (0)