Skip to content

Commit

Permalink
feat(charts): customMemo support to compare function
Browse files Browse the repository at this point in the history
  • Loading branch information
dengfuping committed Oct 7, 2023
1 parent 15ae303 commit 4f9ea1b
Show file tree
Hide file tree
Showing 5 changed files with 130 additions and 11 deletions.
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@
"@testing-library/react-hooks": "^8.0.1",
"@testing-library/user-event": "^14.5.1",
"@types/jest": "^29.5.4",
"@types/lodash": "^4.14.199",
"@types/node": "^20.6.2",
"@types/react": "^18.2.21",
"@umijs/fabric": "^4.0.1",
Expand Down
15 changes: 6 additions & 9 deletions packages/charts/src/Pie/demo/state-change.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React, { useState, useCallback } from 'react';
import React, { useState } from 'react';
import { Pie } from '@oceanbase/charts';

const Demo: React.FC = () => {
Expand Down Expand Up @@ -30,16 +30,13 @@ const Demo: React.FC = () => {
},
]);

// memo function to avoid re-render
const onReady = useCallback(plot => {
console.log(plot);
}, []);

const config = {
data,
angleField: 'value',
colorField: 'type',
onReady,
onReady: plot => {
console.log(plot);
},
};

return (
Expand All @@ -50,7 +47,7 @@ const Demo: React.FC = () => {
setCount(count + 1);
}}
style={{
marginLeft: 16,
marginLeft: 8,
}}
>
外部状态改变不会重新渲染
Expand All @@ -73,7 +70,7 @@ const Demo: React.FC = () => {
]);
}}
style={{
marginLeft: 16,
marginLeft: 8,
}}
>
数据改变重新渲染
Expand Down
99 changes: 99 additions & 0 deletions packages/charts/src/util/__tests__/custom-memo.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
import { isEqualWithFunction } from '../custom-memo';

describe('custom-memo', () => {
it('isEqualWithFunction', () => {
expect(
isEqualWithFunction(
{
a: 1,
b: 2,
data: [{ x: 1, y: 2 }],
},
{
a: 1,
b: 2,
data: [{ x: 1, y: 2 }],
}
)
).toEqual(true);
expect(
isEqualWithFunction(
{
a: 1,
b: 2,
data: [{ x: 1, y: 2 }],
// arrow function
fn: (x, y) => x + y,
},
{
a: 1,
b: 2,
data: [{ x: 1, y: 2 }],
fn: (x, y) => x + y,
}
)
).toEqual(true);
expect(
isEqualWithFunction(
{
a: 1,
b: 2,
data: [{ x: 1, y: 2 }],
// normal function
fn: function (x, y) {
return x + y;
},
},
{
a: 1,
b: 2,
data: [{ x: 1, y: 2 }],
fn: function (x, y) {
return x + y;
},
}
)
).toEqual(true);
expect(
isEqualWithFunction(
{
a: 1,
b: 2,
data: [{ x: 1, y: 2 }],
// normal function abbreviation
fn(x, y) {
return x + y;
},
},
{
a: 1,
b: 2,
data: [{ x: 1, y: 2 }],
fn(x, y) {
return x + y;
},
}
)
).toEqual(true);
expect(
isEqualWithFunction(
{
a: 1,
b: 2,
data: [{ x: 1, y: 2 }],
fn: function (x, y) {
return x + y;
},
},
{
a: 1,
b: 2,
data: [{ x: 1, y: 2 }],
fn(x, y) {
return x + y;
},
}
)
).toEqual(false);
});
});
19 changes: 17 additions & 2 deletions packages/charts/src/util/custom-memo.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,28 @@
import { memo } from 'react';
import type { FunctionComponent } from 'react';
import { isEqual } from 'lodash';
import { isFunction, isEqualWith, isEqual, isPlainObject, maxBy } from 'lodash';
import type { BaseConfig, AllBaseConfig } from '@ant-design/charts';

export function isEqualWithFunction(v1: any, v2: any) {
return isEqualWith(v1, v2, (value1, value2) => {
// function equals
if (isFunction(value1) && isFunction(value2)) {
return value1.toString() === value2.toString();
} else if (isPlainObject(value1) && isPlainObject(value2)) {
const keys1 = Object.keys(value1);
const keys2 = Object.keys(value2);
const keys = maxBy([keys1, keys2], o => o.length);
return keys.every(key => isEqualWithFunction(value1[key], value2[key]));
}
return isEqual(value1, value2);
});
}

export function customMemo<P extends BaseConfig<AllBaseConfig>>(
Component: FunctionComponent<P>,
propsAreEqual?: (prevProps: Readonly<P>, nextProps: Readonly<P>) => boolean
) {
return memo(Component, (prevProps, nextProps) =>
propsAreEqual ? propsAreEqual(prevProps, nextProps) : isEqual(prevProps, nextProps)
propsAreEqual ? propsAreEqual(prevProps, nextProps) : isEqualWithFunction(prevProps, nextProps)
);
}
7 changes: 7 additions & 0 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

0 comments on commit 4f9ea1b

Please sign in to comment.