Skip to content

Commit

Permalink
Replace react-virtualized with react-virtuoso for React 18 compat…
Browse files Browse the repository at this point in the history
…ibility (#11553)
  • Loading branch information
msujew authored Aug 16, 2022
1 parent 3e89a9f commit a58e2f4
Show file tree
Hide file tree
Showing 15 changed files with 116 additions and 226 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
- [core] `updateThemePreference` and `updateThemeFromPreference` removed from `CommonFrontendContribution`. Corresponding functionality as been moved to the respective theme service. `load` removed from `IconThemeService` [#11473](https://github.com/eclipse-theia/theia/issues/11473)
- [core] updated `react` and `react-dom` dependencies to version 18, which introduce new root API for rendering (replaces ReactDOM.render). Since React no longer supports render callbacks, the `onRender` field from `ReactDialog` and `ReactWidget` was removed. [#11455](https://github.com/eclipse-theia/theia/pull/11455) - Contributed on behalf of STMicroelectronics
- [core] removed `WidgetManager.widgetPromises`; use `WidgetManager.widgets` instead. [#11555](https://github.com/eclipse-theia/theia/pull/11555)
- [core] Replaced `react-virtualized` with `react-virtuoso` for tree rendering. Removed the `TreeWidget#forceUpdate`, `TreeWidget#handleScroll` and `TreeWidget.View#renderTreeRow` methods in the process. [#11553](https://github.com/eclipse-theia/theia/pull/11553)

## v1.28.0 - 7/28/2022

Expand Down
3 changes: 2 additions & 1 deletion dependency-check-baseline.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,6 @@
"npm/npmjs/-/jschardet/2.3.0": "Approved for Eclipse Theia: https://dev.eclipse.org/ipzilla/show_bug.cgi?id=22481",
"npm/npmjs/-/jsdom/11.12.0": "Approved as 'works-with': https://dev.eclipse.org/ipzilla/show_bug.cgi?id=23640https://dev.eclipse.org/ipzilla/show_bug.cgi?id=23640",
"npm/npmjs/-/lzma-native/8.0.6": "Approved as 'works-with': https://gitlab.eclipse.org/eclipsefdn/emo-team/iplab/-/issues/1850",
"npm/npmjs/-/playwright-core/1.22.2": "Approved as 'works-with': https://gitlab.eclipse.org/eclipsefdn/emo-team/iplab/-/issues/2734"
"npm/npmjs/-/playwright-core/1.22.2": "Approved as 'works-with': https://gitlab.eclipse.org/eclipsefdn/emo-team/iplab/-/issues/2734",
"npm/npmjs/-/virtuoso.dev/0.2.13": "Approved manually: https://github.com/eclipse-theia/theia/pull/11553"
}
17 changes: 4 additions & 13 deletions doc/Migration.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,19 +25,10 @@ For example:

The `react` and `react-dom` dependencies were upgraded to version 18. Some relevant changes include:

- `ReactDOM.render` is now deprecated and is replaced by `createRoot` from `react-dom/client`
- the new API no longer supports render callbacks
- updates in promises, setTimeout, event handlers are automatically batched

Because the currently used version of `react-virtualized` still depends on React 16, a `resolutions` block is needed in the `package.json` for the React 18 dependencies:

```json
"resolutions": {
"@types/react": "18.0.15",
"@types/react-dom": "18.0.6"
...
}
```
- `ReactDOM.render` is now deprecated and is replaced by `createRoot` from `react-dom/client`
- the new API no longer supports render callbacks
- updates in promises, setTimeout, event handlers are automatically batched
- the dependency `react-virtualized` has been removed in favor of `react-virtuoso`

### v1.24.0

Expand Down
4 changes: 1 addition & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,7 @@
"node": ">=14"
},
"resolutions": {
"**/@types/node": "14",
"@types/react": "18.0.15",
"@types/react-dom": "18.0.6"
"**/@types/node": "14"
},
"devDependencies": {
"@types/chai": "4.3.0",
Expand Down
2 changes: 1 addition & 1 deletion packages/core/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@ export class SomeClass {
- `inversify` (from [`inversify@^5.1.1`](https://www.npmjs.com/package/inversify))
- `react-dom` (from [`react-dom@^18.2.0`](https://www.npmjs.com/package/react-dom))
- `react-dom/client` (from [`react-dom@^18.2.0`](https://www.npmjs.com/package/react-dom))
- `react-virtualized` (from [`react-virtualized@^9.20.0`](https://www.npmjs.com/package/react-virtualized))
- `react-virtuoso` (from [`react-virtuoso@^2.17.0`](https://www.npmjs.com/package/react-virtuoso))
- `vscode-languageserver-protocol` (from [`vscode-languageserver-protocol@~3.15.3`](https://www.npmjs.com/package/vscode-languageserver-protocol))
- `vscode-uri` (from [`vscode-uri@^2.1.1`](https://www.npmjs.com/package/vscode-uri))
- `dompurify` (from [`dompurify@^2.2.9`](https://www.npmjs.com/package/dompurify))
Expand Down
5 changes: 2 additions & 3 deletions packages/core/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,6 @@
"@types/markdown-it": "^12.2.3",
"@types/react": "^18.0.15",
"@types/react-dom": "^18.0.6",
"@types/react-virtualized": "^9.18.3",
"@types/route-parser": "^0.1.1",
"@types/safer-buffer": "^2.1.0",
"@types/ws": "^5.1.2",
Expand Down Expand Up @@ -62,7 +61,7 @@
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react-tooltip": "^4.2.21",
"react-virtualized": "^9.20.0",
"react-virtuoso": "^2.17.0",
"reflect-metadata": "^0.1.10",
"route-parser": "^0.0.5",
"safer-buffer": "^2.1.2",
Expand Down Expand Up @@ -112,7 +111,7 @@
"inversify",
"react-dom",
"react-dom/client",
"react-virtualized",
"react-virtuoso",
"vscode-languageserver-protocol",
"vscode-uri"
],
Expand Down
1 change: 0 additions & 1 deletion packages/core/shared/react-virtualized/index.d.ts

This file was deleted.

1 change: 0 additions & 1 deletion packages/core/shared/react-virtualized/index.js

This file was deleted.

1 change: 1 addition & 0 deletions packages/core/shared/react-virtuoso/index.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from 'react-virtuoso';
1 change: 1 addition & 0 deletions packages/core/shared/react-virtuoso/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
module.exports = require('react-virtuoso');
92 changes: 26 additions & 66 deletions packages/core/src/browser/tree/tree-widget.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ import { notEmpty } from '../../common/objects';
import { isOSX } from '../../common/os';
import { ReactWidget } from '../widgets/react-widget';
import * as React from 'react';
import { List, ListRowRenderer, ScrollParams, CellMeasurer, CellMeasurerCache } from 'react-virtualized';
import { Virtuoso, VirtuosoHandle } from 'react-virtuoso';
import { TopDownTreeIterator } from './tree-iterator';
import { SearchBox, SearchBoxFactory, SearchBoxProps } from './search-box';
import { TreeSearch } from './tree-search';
Expand Down Expand Up @@ -256,7 +256,7 @@ export class TreeWidget extends ReactWidget implements StatefulWidget {
this.labelProvider.onDidChange(e => {
for (const row of this.rows.values()) {
if (e.affects(row)) {
this.forceUpdate();
this.update();
return;
}
}
Expand Down Expand Up @@ -347,9 +347,9 @@ export class TreeWidget extends ReactWidget implements StatefulWidget {
* Update the `scrollToRow`.
* @param updateOptions the tree widget force update options.
*/
protected updateScrollToRow(updateOptions?: TreeWidget.ForceUpdateOptions): void {
protected updateScrollToRow(): void {
this.scrollToRow = this.getScrollToRow();
this.forceUpdate(updateOptions);
this.update();
}

protected scheduleUpdateScrollToRow = debounce(this.updateScrollToRow);
Expand All @@ -374,22 +374,6 @@ export class TreeWidget extends ReactWidget implements StatefulWidget {
protected readonly updateDecorations = debounce(() => this.doUpdateDecorations(), 150);
protected async doUpdateDecorations(): Promise<void> {
this.decorations = await this.decoratorService.getDecorations(this.model);
this.forceUpdate();
}

/**
* Force deep resizing and rendering of rows.
* https://github.com/bvaughn/react-virtualized/blob/master/docs/List.md#recomputerowheights-index-number
*/
protected forceUpdate({ resize }: TreeWidget.ForceUpdateOptions = { resize: false }): void {
if (this.view && this.view.list) {
if (resize && this.isVisible) {
this.view.cache.clearAll();
this.view.list.recomputeRowHeights();
} else {
this.view.list.forceUpdateGrid();
}
}
this.update();
}

Expand Down Expand Up @@ -436,7 +420,7 @@ export class TreeWidget extends ReactWidget implements StatefulWidget {

protected override onResize(msg: Widget.ResizeMessage): void {
super.onResize(msg);
this.forceUpdate({ resize: true });
this.update();
}

protected render(): React.ReactNode {
Expand Down Expand Up @@ -491,7 +475,6 @@ export class TreeWidget extends ReactWidget implements StatefulWidget {
rows={rows}
renderNodeRow={this.renderNodeRow}
scrollToRow={this.scrollToRow}
handleScroll={this.handleScroll}
/>;
}
// eslint-disable-next-line no-null/no-null
Expand All @@ -517,21 +500,14 @@ export class TreeWidget extends ReactWidget implements StatefulWidget {
}
}

/**
* Handle the scroll event.
*/
protected readonly handleScroll = (info: ScrollParams) => {
this.node.scrollTop = info.scrollTop;
};

/**
* Render the node row.
*/
protected readonly renderNodeRow = (row: TreeWidget.NodeRow) => this.doRenderNodeRow(row);
/**
* Actually render the node row.
*/
protected doRenderNodeRow({ index, node, depth }: TreeWidget.NodeRow): React.ReactNode {
protected doRenderNodeRow({ node, depth }: TreeWidget.NodeRow): React.ReactNode {
return <React.Fragment>
{this.renderIndent(node, { depth })}
{this.renderNode(node, { depth })}
Expand Down Expand Up @@ -1128,9 +1104,11 @@ export class TreeWidget extends ReactWidget implements StatefulWidget {
this.addKeyListener(this.node, Key.ESCAPE, event => this.handleEscape(event));
// eslint-disable-next-line @typescript-eslint/no-explicit-any
this.addEventListener<any>(this.node, 'ps-scroll-y', (e: Event & { target: { scrollTop: number } }) => {
if (this.view && this.view.list && this.view.list.Grid) {
if (this.view && this.view.list) {
const { scrollTop } = e.target;
this.view.list.Grid.handleScrollEvent({ scrollTop });
this.view.list.scrollTo({
top: scrollTop
});
}
});
}
Expand Down Expand Up @@ -1444,15 +1422,6 @@ export class TreeWidget extends ReactWidget implements StatefulWidget {

}
export namespace TreeWidget {
/**
* Representation of the tree force update options.
*/
export interface ForceUpdateOptions {
/**
* Controls whether to force a resize of the widget.
*/
resize: boolean
}
/**
* Representation of a tree node row.
*/
Expand Down Expand Up @@ -1490,38 +1459,29 @@ export namespace TreeWidget {
* The list of node rows.
*/
rows: NodeRow[]
handleScroll: (info: ScrollParams) => void
renderNodeRow: (row: NodeRow) => React.ReactNode
}
export class View extends React.Component<ViewProps> {
list: List | undefined;
readonly cache = new CellMeasurerCache({
fixedWidth: true
});
list: VirtuosoHandle | undefined;
override render(): React.ReactNode {
const { rows, width, height, scrollToRow, handleScroll } = this.props;
return <List
ref={list => this.list = (list || undefined)}
const { rows, width, height, scrollToRow } = this.props;
return <Virtuoso
ref={list => {
this.list = (list || undefined);
if (this.list && scrollToRow !== undefined) {
this.list.scrollIntoView({
index: scrollToRow,
align: 'center'
});
}
}}
totalCount={rows.length}
itemContent={index => this.props.renderNodeRow(rows[index])}
width={width}
height={height}
rowCount={rows.length}
rowHeight={this.cache.rowHeight}
rowRenderer={this.renderTreeRow}
scrollToIndex={scrollToRow}
onScroll={handleScroll}
tabIndex={-1}
// This is a pixel value, it will scan 200px to the top and bottom of the current view
overscan={500}
/>;
}
protected renderTreeRow: ListRowRenderer = ({ key, index, style, parent }) => {
const row = this.props.rows[index]!;
return <CellMeasurer
cache={this.cache}
columnIndex={0}
key={key}
parent={parent}
rowIndex={index}>
<div key={key} style={style}>{this.props.renderNodeRow(row)}</div>
</CellMeasurer>;
};
}
}
1 change: 1 addition & 0 deletions packages/git/src/browser/history/git-history-support.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ export class GitHistorySupport implements ScmHistorySupport {
const gitOptions: Git.Options.Log = {
uri: options ? options.uri : undefined,
maxCount: options ? options.maxCount : undefined,
range: options?.range,
shortSha: true
};

Expand Down
Loading

0 comments on commit a58e2f4

Please sign in to comment.