Skip to content

Commit

Permalink
perf(statistic): perf statistic
Browse files Browse the repository at this point in the history
  • Loading branch information
HaixingOoO committed Nov 27, 2023
1 parent f4de882 commit 8658aaf
Show file tree
Hide file tree
Showing 6 changed files with 76 additions and 51 deletions.
14 changes: 14 additions & 0 deletions src/hooks/useIsFirstRender.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import { useRef } from 'react';

const useIsFirstRender = () => {
const isFirstRenderRef = useRef(true);

if (isFirstRenderRef.current) {
isFirstRenderRef.current = false;
return true;
}

return isFirstRenderRef.current;
};

export default useIsFirstRender;
43 changes: 17 additions & 26 deletions src/statistic/Statistic.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import { StyledProps } from '../common';
import useConfig from '../hooks/useConfig';
import useGlobalIcon from '../hooks/useGlobalIcon';
import useDefaultProps from '../hooks/useDefaultProps';
import useIsFirstRender from '../hooks/useIsFirstRender';

import Skeleton from '../skeleton';
import Tween from '../_common/js/statistic/tween';
Expand Down Expand Up @@ -51,8 +52,8 @@ const Statistic = forwardRef<StatisticRef, StatisticProps>((props, ref) => {
*/
const [innerValue, setInnerValue] = useState(animation?.valueFrom ?? value);
const numberValue = useMemo(() => (isNumber(value) ? value : 0), [value]);

const tween = useRef(null);
const isFirstRender = useIsFirstRender();

const start = (from: number = animation?.valueFrom ?? 0, to: number = numberValue) => {
if (from !== to) {
Expand All @@ -63,7 +64,7 @@ const Statistic = forwardRef<StatisticRef, StatisticProps>((props, ref) => {
to: {
value: to,
},
duration: props.animation.duration,
duration: animation?.duration,
onUpdate: (keys) => {
setInnerValue(keys.value);
},
Expand All @@ -76,21 +77,20 @@ const Statistic = forwardRef<StatisticRef, StatisticProps>((props, ref) => {
};

const formatValue = useMemo(() => {
// eslint-disable-next-line no-underscore-dangle
let _value: number | undefined | string = innerValue;
let formatInnerValue: number | string | undefined = innerValue;

if (isFunction(format)) {
return format(_value);
return format(formatInnerValue);
}
const options = {
minimumFractionDigits: decimalPlaces || 0,
maximumFractionDigits: decimalPlaces || 20,
useGrouping: !!separator,
};
// replace的替换的方案仅能应对大部分地区
_value = _value.toLocaleString(undefined, options).replace(/,|,/g, separator);
formatInnerValue = formatInnerValue.toLocaleString(undefined, options).replace(/,|,/g, separator);

return _value;
return formatInnerValue;
}, [innerValue, decimalPlaces, separator, format]);

const valueStyle = useMemo(
Expand All @@ -102,37 +102,28 @@ const Statistic = forwardRef<StatisticRef, StatisticProps>((props, ref) => {
);

useEffect(() => {
animation && animationStart && start();
return () => {
if (tween.current) {
tween.current.stop();
}
};
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);
// 第一次渲染不执行,否则导致初始formValue失效
console.log('isFirstRender', isFirstRender);
if (isFirstRender) return;

useEffect(() => {
animationStart && animation && !tween.current && start();
setInnerValue(value);

animationStart && animation && start();

return () => {
if (tween.current) {
tween.current.stop();
}
};

// eslint-disable-next-line react-hooks/exhaustive-deps
}, [animationStart]);
}, [value]);

useEffect(() => {
if (tween.current) {
tween.current?.stop();
tween.current = null;
}
setInnerValue(value);

animationStart && animation && start();
animationStart && animation && !tween.current && start();

// eslint-disable-next-line react-hooks/exhaustive-deps
}, [value]);
}, [animationStart]);

useImperativeHandle(ref, () => ({
start,
Expand Down
46 changes: 31 additions & 15 deletions src/statistic/__tests__/statistic.test.tsx
Original file line number Diff line number Diff line change
@@ -1,18 +1,8 @@
import React from 'react';
import { render, fireEvent, waitFor } from '@test/utils';
import { vi } from 'vitest';
import { render, fireEvent, mockDelay } from '@test/utils';
import { ArrowTriangleDownFilledIcon, ArrowTriangleUpFilledIcon } from 'tdesign-icons-react';
import Statistic from '../index';

beforeEach(() => {
vi.useFakeTimers({ shouldAdvanceTime: true });
});

afterEach(() => {
vi.runOnlyPendingTimers();
vi.useRealTimers();
});

describe('Statistic 组件测试', () => {
/**
* props
Expand Down Expand Up @@ -117,10 +107,36 @@ describe('Statistic 组件测试', () => {

fireEvent.click(document.querySelector('#button'));

vi.advanceTimersByTime(2000);
await mockDelay(2000);

await waitFor(() => {
expect(document.querySelector('.t-statistic-content-value')).toHaveTextContent('82.76');
});
expect(document.querySelector('.t-statistic-content-value')).toHaveTextContent('82.76');
});

/**
* not animation config display value
*/
test('not animation', async () => {
render(<Statistic title="Total Assets" value={82.76} format={(value) => +value.toFixed(2)} />);

expect(document.querySelector('.t-statistic-content-value')).toHaveTextContent('82.76');
});

/**
* have animation config display valueFrom
*/
test('not animation', async () => {
render(
<Statistic
title="Total Assets"
value={82.76}
animation={{
valueFrom: 0,
duration: 2000,
}}
format={(value) => +value.toFixed(2)}
/>,
);

expect(document.querySelector('.t-statistic-content-value')).toHaveTextContent('0');
});
});
19 changes: 11 additions & 8 deletions src/statistic/_example/combination.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -32,16 +32,19 @@ const CombinationStatistic = () => {
color="red"
extra={
<Space direction="vertical" size={0}>
<span>
the day before
<IconFont name="arrow-up" style={{ color: '#d54941' }} />
<Space align="center" size={7}>
<div style={{ width: '120px' }}>the day before</div>
<IconFont name="arrow-up" style={{ color: '#d54941', fontSize: 'var(--td-font-size-body-large)' }} />
9%
</span>
<span>
last week
<IconFont name="arrow-down" style={{ color: '#2ba471' }} />
</Space>
<Space align="center" size={7}>
<div style={{ width: '120px' }}>last week</div>
<IconFont
name="arrow-down"
style={{ color: '#2ba471', fontSize: 'var(--td-font-size-body-large)' }}
/>
9%
</span>
</Space>
</Space>
}
></Statistic>
Expand Down
2 changes: 1 addition & 1 deletion src/statistic/_example/loading.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import React from 'react';
import { Space, Switch, Statistic } from 'tdesign-react';

const LoadingStatistic = () => {
const [loading, setLoading] = React.useState(false);
const [loading, setLoading] = React.useState(true);
return (
<Space direction="vertical">
<Switch value={loading} onChange={(value) => setLoading(value)} size="large" />
Expand Down
3 changes: 2 additions & 1 deletion src/statistic/_example/slot.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,14 @@ import { Space, Statistic } from 'tdesign-react';
import { ControlPlatformIcon, ArrowTriangleDownFilledIcon } from 'tdesign-icons-react';

const SlotStatistic = () => (
<Space>
<Space size={32}>
<Statistic title="Total Assets" value={56.32} unit="%" prefix={<ControlPlatformIcon />}></Statistic>
<Statistic title="Total Assets" value={176059} prefix="$" unit="%" trend="increase" />

<Statistic
title="Total Assets"
value={62.58}
unit="%"
suffix={<ArrowTriangleDownFilledIcon style={{ color: '#ee4d38' }} />}
></Statistic>
</Space>
Expand Down

0 comments on commit 8658aaf

Please sign in to comment.