Skip to content

Commit

Permalink
fix: 减少开启 ReactDOM.unstable_batchedUpdates 后的重渲染次数 (#2971)
Browse files Browse the repository at this point in the history
* fix: 减少开启 ReactDOM.unstable_batchedUpdates 后的重渲染次数

* test: 补充单测

* fix: 比较 dataCfg 使用 Object.is
  • Loading branch information
lijinke666 authored Nov 14, 2024
1 parent 599d7a4 commit 9007e8e
Show file tree
Hide file tree
Showing 9 changed files with 95 additions and 59 deletions.
10 changes: 5 additions & 5 deletions packages/s2-core/__tests__/unit/sheet-type/pivot-sheet-spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -773,24 +773,24 @@ describe('PivotSheet Tests', () => {

test('should rebuild hidden columns detail by status', async () => {
// 重新更新, 但是没有隐藏列信息
await s2.render({ reloadData: false, reBuildHiddenColumnsDetail: true });
await s2.render({ reloadData: false, rebuildHiddenColumnsDetail: true });

expect(mockHideColumnsByThunkGroup).toHaveBeenCalledTimes(0);

s2.store.set('hiddenColumnsDetail', [
null,
] as unknown as HiddenColumnsInfo[]);

// 重新更新, 有隐藏列信息, 但是 reBuildHiddenColumnsDetail 为 false
// 重新更新, 有隐藏列信息, 但是 rebuildHiddenColumnsDetail 为 false
await s2.render({
reloadData: false,
reBuildHiddenColumnsDetail: false,
rebuildHiddenColumnsDetail: false,
});

expect(mockHideColumnsByThunkGroup).toHaveBeenCalledTimes(0);

// 重新更新, 有隐藏列信息, 且 reBuildHiddenColumnsDetail 为 true
await s2.render({ reloadData: false, reBuildHiddenColumnsDetail: true });
// 重新更新, 有隐藏列信息, 且 rebuildHiddenColumnsDetail 为 true
await s2.render({ reloadData: false, rebuildHiddenColumnsDetail: true });

expect(mockHideColumnsByThunkGroup).toHaveBeenCalledTimes(1);
});
Expand Down
2 changes: 1 addition & 1 deletion packages/s2-core/src/common/interface/s2Options.ts
Original file line number Diff line number Diff line change
Expand Up @@ -386,5 +386,5 @@ export interface S2RenderOptions {
/**
* 是否重新生成列头隐藏信息
*/
reBuildHiddenColumnsDetail?: boolean;
rebuildHiddenColumnsDetail?: boolean;
}
6 changes: 3 additions & 3 deletions packages/s2-core/src/sheet-type/spread-sheet.ts
Original file line number Diff line number Diff line change
Expand Up @@ -423,7 +423,7 @@ export abstract class SpreadSheet extends EE {
const {
reloadData = true,
rebuildDataSet = false,
reBuildHiddenColumnsDetail = true,
rebuildHiddenColumnsDetail = true,
} = options || {};

this.emit(S2Event.LAYOUT_BEFORE_RENDER);
Expand All @@ -439,7 +439,7 @@ export abstract class SpreadSheet extends EE {

this.buildFacet();

if (reBuildHiddenColumnsDetail) {
if (rebuildHiddenColumnsDetail) {
await this.initHiddenColumnsDetail();
}

Expand All @@ -456,7 +456,7 @@ export abstract class SpreadSheet extends EE {
s2.render({
reloadData: true;
rebuildDataSet: true;
reBuildHiddenColumnsDetail: true;
rebuildHiddenColumnsDetail: true;
})
*/
public async render(options?: S2RenderOptions | boolean): Promise<void> {
Expand Down
2 changes: 1 addition & 1 deletion packages/s2-core/src/utils/hide-columns.ts
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,7 @@ export const hideColumns = async (
spreadsheet.store.set('hiddenColumnsDetail', hiddenColumnsDetail);
await spreadsheet.render({
reloadData: false,
reBuildHiddenColumnsDetail: false,
rebuildHiddenColumnsDetail: false,
});
};

Expand Down
98 changes: 60 additions & 38 deletions packages/s2-react/__tests__/unit/hooks/useSpreadSheet-spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ describe('useSpreadSheet tests', () => {
fields: S2DataConfig['fields'] = mockDataConfig.fields,
): SheetComponentProps => {
return {
sheetType: 'pivot' as const,
spreadsheet: () =>
new PivotSheet(getContainer(), mockDataConfig, s2Options as S2Options),
options: s2Options,
Expand All @@ -35,9 +36,7 @@ describe('useSpreadSheet tests', () => {

test('should build spreadSheet', async () => {
const props = getConfig();
const { result } = renderHook(() =>
useSpreadSheet({ ...props, sheetType: 'pivot' }),
);
const { result } = renderHook(() => useSpreadSheet({ ...props }));

await waitFor(() => {
expect(result.current.s2Ref).toBeDefined();
Expand All @@ -47,7 +46,6 @@ describe('useSpreadSheet tests', () => {
test('should cannot change table size when width or height updated and disable adaptive', async () => {
const props = {
...getConfig(),
sheetType: 'pivot' as const,
adaptive: false,
};
const { result } = renderHook(() => useSpreadSheet(props));
Expand Down Expand Up @@ -126,7 +124,6 @@ describe('useSpreadSheet tests', () => {

const props = {
...getConfig(),
sheetType: 'pivot' as const,
onDestroy: onDestroyFromProps,
};
const { result, unmount } = renderHook(() => useSpreadSheet(props));
Expand Down Expand Up @@ -160,7 +157,6 @@ describe('useSpreadSheet tests', () => {

const props = {
...getConfig(),
sheetType: 'pivot' as const,
onMounted,
};
const { result } = renderHook(() => useSpreadSheet(props));
Expand All @@ -173,48 +169,74 @@ describe('useSpreadSheet tests', () => {
});
});

test('should call onUpdate and onUpdateAfterRender when sheet updated', async () => {
const onUpdate = jest.fn();
const onUpdateAfterRender = jest.fn();

const props = {
...getConfig(),
sheetType: 'pivot' as const,
onUpdate,
onUpdateAfterRender,
};
const { rerender } = renderHook(
(innerProps) => useSpreadSheet(innerProps),
{
initialProps: props,
test.each([
{
updatedProps: {
options: { width: 200 },
},
);

await waitFor(() => {
expect(onUpdate).toHaveBeenCalledTimes(0);
expect(onUpdateAfterRender).toHaveBeenCalledTimes(0);
});

act(() => {
rerender({ ...props, options: { width: 200 } });
});

await waitFor(() => {
expect(onUpdate).toHaveBeenCalledWith({
updateOptions: {
rebuildDataSet: false,
reloadData: false,
},
},
{
updatedProps: {
themeCfg: { name: 'dark' },
},
updateOptions: {
rebuildDataSet: false,
reloadData: false,
},
},
{
updatedProps: {
dataCfg: { fields: ['test'] },
},
updateOptions: {
rebuildDataSet: false,
reloadData: true,
},
},
])(
'should call onUpdate and onUpdateAfterRender when sheet %o updated',
async ({ updatedProps, updateOptions }) => {
const onUpdate = jest.fn();
const onUpdateAfterRender = jest.fn();

const props = {
...getConfig(),
onUpdate,
onUpdateAfterRender,
};
const { rerender } = renderHook(
(innerProps) => useSpreadSheet(innerProps),
{
initialProps: props,
},
);

await waitFor(() => {
expect(onUpdate).toHaveBeenCalledTimes(0);
expect(onUpdateAfterRender).toHaveBeenCalledTimes(0);
});
expect(onUpdateAfterRender).toHaveBeenCalledTimes(1);
});
});

act(() => {
rerender({ ...props, ...updatedProps });
});

await waitFor(() => {
expect(onUpdate).toHaveBeenCalledWith(updateOptions);
expect(onUpdateAfterRender).toHaveBeenCalledTimes(1);
});
},
);

test('should use custom render mode by onUpdate', async () => {
const onUpdate = jest.fn((options) => ({ ...options, reloadData: true }));
const onUpdateAfterRender = jest.fn();

const props = {
...getConfig(),
sheetType: 'pivot' as const,
onUpdate,
onUpdateAfterRender,
};
Expand All @@ -226,7 +248,7 @@ describe('useSpreadSheet tests', () => {
);

act(() => {
rerender({ ...props, options: { width: 200 } });
rerender({ ...props, options: { width: 300 } });
});

await waitFor(() => {
Expand Down
19 changes: 15 additions & 4 deletions packages/s2-react/src/hooks/useSpreadSheet.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
/* eslint-disable max-lines-per-function */
import type { S2DataConfig, S2Options, ThemeCfg } from '@antv/s2';
import { PivotSheet, SpreadSheet, TableSheet } from '@antv/s2';
import { useUpdate, useUpdateEffect } from 'ahooks';
import { identity } from 'lodash';
import { identity, isEqual } from 'lodash';
import React from 'react';
import type { SheetComponentOptions, SheetComponentProps } from '../components';
import { getSheetComponentOptions } from '../utils';
Expand Down Expand Up @@ -106,6 +107,7 @@ export function useSpreadSheet(props: SheetComponentProps) {

updatePrevDepsRef.current = [dataCfg, options!, themeCfg!];

let rerender = false;
let reloadData = false;
let rebuildDataSet = false;

Expand All @@ -119,24 +121,33 @@ export function useSpreadSheet(props: SheetComponentProps) {
}

reloadData = true;
rerender = true;
s2Ref.current?.setDataCfg(dataCfg);
}

if (!Object.is(prevOptions, options)) {
if (!Object.is(prevOptions?.hierarchyType, options?.hierarchyType)) {
if (!isEqual(prevOptions, options)) {
if (prevOptions?.hierarchyType !== options?.hierarchyType) {
rebuildDataSet = true;
reloadData = true;
s2Ref.current?.setDataCfg(dataCfg);
}

rerender = true;
s2Ref.current?.setOptions(options as S2Options);
s2Ref.current?.changeSheetSize(options!.width, options!.height);
}

if (!Object.is(prevThemeCfg, themeCfg)) {
if (!isEqual(prevThemeCfg, themeCfg)) {
rerender = true;
s2Ref.current?.setThemeCfg(themeCfg);
}

if (!rerender) {
setLoading(false);

return;
}

/**
* onUpdate 交出控制权
* 由传入方决定最终的 render 模式
Expand Down
2 changes: 1 addition & 1 deletion s2-site/docs/api/basic-class/spreadsheet.zh.md
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ s2.isPivotMode()
| setOptions | 更新表格配置 | (options: [S2Options](/docs/api/general/S2Options), reset?: boolean) => void | `reset` 参数需在 `@antv/s2^1.34.0`版本使用 |
| resetDataCfg | 重置表格数据 | () => void | |
| resetOptions | 重置表格配置 | () => void | |
| render | 重新渲染表格,如果 `reloadData` = true, 则会重新计算数据,`rebuildDataSet` = true, 重新构建数据集,`reBuildHiddenColumnsDetail` = true 重新构建隐藏列信息 | `(reloadData?: boolean \| { reloadData?: boolean, rebuildDataSet?: boolean; reBuildHiddenColumnsDetail?: boolean }) => Promise<void>` | |
| render | 重新渲染表格,如果 `reloadData` = true, 则会重新计算数据,`rebuildDataSet` = true, 重新构建数据集,`rebuildHiddenColumnsDetail` = true 重新构建隐藏列信息 | `(reloadData?: boolean \| { reloadData?: boolean, rebuildDataSet?: boolean; rebuildHiddenColumnsDetail?: boolean }) => Promise<void>` | |
| destroy | 销毁表格 | `() => void` | |
| setThemeCfg | 更新主题配置 (含主题 schema, 色板,主题名) | (themeCfg: [ThemeCfg](/docs/api/general/S2Theme/#themecfg)) => void | |
| setTheme | 更新主题 (只包含主题 scheme) | (theme: [S2Theme](/docs/api/general/S2Theme/#s2theme)) => void | |
Expand Down
2 changes: 1 addition & 1 deletion s2-site/docs/api/components/sheet-component.zh.md
Original file line number Diff line number Diff line change
Expand Up @@ -354,7 +354,7 @@ type SheetComponentOptions = S2Options<
| -- | -- | -- | -- | --- |
| reloadData | 是否重新加载数据 | `boolean` | | |
| rebuildDataSet | 是否重新生成数据集 | `boolean` | | |
| reBuildHiddenColumnsDetail | 是否重新生成列头隐藏信息 | `boolean` | | |
| rebuildHiddenColumnsDetail | 是否重新生成列头隐藏信息 | `boolean` | | |

<embed src="@/docs/common/view-meta.zh.md"></embed>
<embed src="@/docs/common/interaction.zh.md"></embed>
13 changes: 8 additions & 5 deletions s2-site/docs/manual/migration-v2.zh.md
Original file line number Diff line number Diff line change
Expand Up @@ -621,17 +621,20 @@ render 函数的参数从 `boolean` 扩展为 `boolean | object`, 当为 `boolea
+ s2.render({ reloadData: false }) // 等价于 s2.render(false)
+ s2.render({
+ reloadData: false,
+ reBuildHiddenColumnsDetail: false,
+ rebuildHiddenColumnsDetail: false,
+ });
```

`reBuildDataSet` 重命名为 `rebuildDataSet`:
`reBuildHiddenColumnsDetail` 重命名为 `rebuildHiddenColumnsDetail`:

```diff
+ s2.render({
- reBuildDataSet: false,
+ rebuildDataSet: false,
+ });
s2.render({
- reBuildDataSet: false,
+ rebuildDataSet: false,
- reBuildHiddenColumnsDetail: false,
+ rebuildHiddenColumnsDetail: false,
});
```

#### 小计总计配置参数变更
Expand Down

0 comments on commit 9007e8e

Please sign in to comment.