@hsu-react/ui 2.5.5 → 2.5.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (40) hide show
  1. package/es/components/Chart/Bar/index.js +6 -1
  2. package/es/components/Chart/Bubble/index.js +6 -1
  3. package/es/components/Chart/Common/index.js +6 -1
  4. package/es/components/Chart/Gauge/index.js +6 -1
  5. package/es/components/Chart/Heatmap/index.js +9 -2
  6. package/es/components/Chart/Line/index.js +6 -1
  7. package/es/components/Chart/Pie/Pie3D/index.js +15 -7
  8. package/es/components/Chart/Pie/index.js +9 -2
  9. package/es/components/Chart/Polar/index.js +9 -2
  10. package/es/components/Chart/Radar/index.js +6 -1
  11. package/es/hooks/useShallowStable.d.ts +32 -0
  12. package/es/hooks/useShallowStable.js +54 -0
  13. package/lib/components/Chart/Bar/index.js +6 -1
  14. package/lib/components/Chart/Bubble/index.js +6 -1
  15. package/lib/components/Chart/Common/index.js +6 -1
  16. package/lib/components/Chart/Gauge/index.js +6 -1
  17. package/lib/components/Chart/Heatmap/index.js +9 -2
  18. package/lib/components/Chart/Line/index.js +6 -1
  19. package/lib/components/Chart/Pie/Pie3D/index.js +15 -7
  20. package/lib/components/Chart/Pie/index.js +9 -2
  21. package/lib/components/Chart/Polar/index.js +9 -2
  22. package/lib/components/Chart/Radar/index.js +6 -1
  23. package/lib/hooks/useShallowStable.d.ts +32 -0
  24. package/lib/hooks/useShallowStable.js +59 -0
  25. package/package.json +1 -1
  26. package/src/__tests__/callbackDepsGuard.test.ts +4 -51
  27. package/src/__tests__/depsScan.ts +158 -0
  28. package/src/__tests__/freshObjectDepsGuard.test.ts +144 -0
  29. package/src/components/Chart/Bar/index.tsx +6 -1
  30. package/src/components/Chart/Bubble/index.tsx +6 -1
  31. package/src/components/Chart/Common/index.tsx +6 -1
  32. package/src/components/Chart/Gauge/index.tsx +6 -1
  33. package/src/components/Chart/Heatmap/index.tsx +20 -12
  34. package/src/components/Chart/Line/index.tsx +6 -1
  35. package/src/components/Chart/Pie/Pie3D/index.tsx +12 -3
  36. package/src/components/Chart/Pie/index.tsx +10 -2
  37. package/src/components/Chart/Polar/index.tsx +10 -2
  38. package/src/components/Chart/Radar/index.tsx +6 -1
  39. package/src/components/Chart/optionMemo.test.tsx +232 -0
  40. package/src/hooks/useShallowStable.ts +65 -0
@@ -17,6 +17,7 @@ import { buildCartesianSeriesOptions, createDefaultCategoryXAxis, createDefaultV
17
17
  import { resolveChartChrome } from "../_utils/chartTheme";
18
18
  import useIsDark from "../../../hooks/useIsDark";
19
19
  import useLatestRef from "../../../hooks/useLatestRef";
20
+ import useShallowStable from "../../../hooks/useShallowStable";
20
21
  import { jsx as _jsx } from "react/jsx-runtime";
21
22
  var ChartBar = function ChartBar(props) {
22
23
  var className = props.className,
@@ -45,7 +46,11 @@ var ChartBar = function ChartBar(props) {
45
46
  legendVisibleCount = _props$legendVisibleC === void 0 ? 8 : _props$legendVisibleC,
46
47
  _props$legendScrollIn = props.legendScrollInterval,
47
48
  legendScrollInterval = _props$legendScrollIn === void 0 ? 1500 : _props$legendScrollIn,
48
- coreOption = _objectWithoutProperties(props, _excluded);
49
+ restOption = _objectWithoutProperties(props, _excluded);
50
+ // rest 解构出来的对象每次渲染都是新引用,直接进依赖数组会让 chartOption 的 memo
51
+ // 恒不命中 —— 父组件每渲染一次就重跑一次 setOption(notMerge),动画重播、悬浮态被清掉。
52
+ // useShallowStable 让它回到值语义:内容浅相等就复用同一引用,真变了立刻透出新引用。
53
+ var coreOption = useShallowStable(restOption);
49
54
  var chartRef = useRef(null);
50
55
  var chartInstanceRef = useRef(null);
51
56
  // Defers `echarts.init` until the container has a box — see the hook for why
@@ -22,6 +22,7 @@ import styles from "../index.module.scss";
22
22
  import * as echarts from "echarts";
23
23
  import { defaultBubbleColorList, drawCircles } from "../_utils/bubble";
24
24
  import { useLatestRef } from "../../../hooks/useLatestRef";
25
+ import useShallowStable from "../../../hooks/useShallowStable";
25
26
 
26
27
  // Extended data item type containing all properties the chart needs
27
28
  import { jsx as _jsx } from "react/jsx-runtime";
@@ -38,7 +39,11 @@ var Bubble = function Bubble(props) {
38
39
  title = props.title,
39
40
  onChart = props.onChart,
40
41
  onClick = props.onClick,
41
- coreOption = _objectWithoutProperties(props, _excluded);
42
+ restOption = _objectWithoutProperties(props, _excluded);
43
+ // rest 解构出来的对象每次渲染都是新引用,直接进依赖数组会让 chartOption 的 memo
44
+ // 恒不命中 —— 父组件每渲染一次就重跑一次 setOption(notMerge),动画重播、悬浮态被清掉。
45
+ // useShallowStable 让它回到值语义:内容浅相等就复用同一引用,真变了立刻透出新引用。
46
+ var coreOption = useShallowStable(restOption);
42
47
  var chartRef = useRef(null);
43
48
  var chartInstanceRef = useRef(null);
44
49
  var resizeObserverRef = useRef(null);
@@ -12,12 +12,17 @@ import useContainerReady from "../_hooks/useContainerReady";
12
12
  import styles from "../index.module.scss";
13
13
  import * as echarts from "echarts";
14
14
  import { useLatestRef } from "../../../hooks/useLatestRef";
15
+ import useShallowStable from "../../../hooks/useShallowStable";
15
16
  import { jsx as _jsx } from "react/jsx-runtime";
16
17
  var Common = function Common(props) {
17
18
  var className = props.className,
18
19
  style = props.style,
19
20
  onChart = props.onChart,
20
- coreOption = _objectWithoutProperties(props, _excluded);
21
+ restOption = _objectWithoutProperties(props, _excluded);
22
+ // rest 解构出来的对象每次渲染都是新引用,直接进依赖数组会让 chartOption 的 memo
23
+ // 恒不命中 —— 父组件每渲染一次就重跑一次 setOption(notMerge),动画重播、悬浮态被清掉。
24
+ // useShallowStable 让它回到值语义:内容浅相等就复用同一引用,真变了立刻透出新引用。
25
+ var coreOption = useShallowStable(restOption);
21
26
  var chartRef = useRef(null);
22
27
  var chartInstanceRef = useRef(null);
23
28
  // Defers `echarts.init` until the container has a box — see the hook for why
@@ -11,6 +11,7 @@ import * as echarts from "echarts";
11
11
  import useContainerReady from "../_hooks/useContainerReady";
12
12
  import React, { useCallback, useEffect, useMemo, useRef } from "react";
13
13
  import styles from "../index.module.scss";
14
+ import useShallowStable from "../../../hooks/useShallowStable";
14
15
  import { jsx as _jsx } from "react/jsx-runtime";
15
16
  var Gauge = function Gauge(props) {
16
17
  var className = props.className,
@@ -29,7 +30,11 @@ var Gauge = function Gauge(props) {
29
30
  title = _ref.title,
30
31
  _ref$color = _ref.color,
31
32
  color = _ref$color === void 0 ? "#1675FB" : _ref$color,
32
- coreSeries = _objectWithoutProperties(_ref, _excluded);
33
+ restSeries = _objectWithoutProperties(_ref, _excluded);
34
+ // rest 解构出来的对象每次渲染都是新引用,直接进依赖数组会让 chartOption 的 memo
35
+ // 恒不命中 —— 父组件每渲染一次就重跑一次 setOption(notMerge),动画重播、悬浮态被清掉。
36
+ // useShallowStable 让它回到值语义:内容浅相等就复用同一引用,真变了立刻透出新引用。
37
+ var coreSeries = useShallowStable(restSeries);
33
38
  var chartRef = useRef(null);
34
39
  var chartInstanceRef = useRef(null);
35
40
  // Defers `echarts.init` until the container has a box — see the hook for why
@@ -21,7 +21,10 @@ import { createDefaultHeatmapXAxis, createDefaultHeatmapYAxis } from "../_utils/
21
21
  import { resolveChartChrome } from "../_utils/chartTheme";
22
22
  import useIsDark from "../../../hooks/useIsDark";
23
23
  import { useLatestRef } from "../../../hooks/useLatestRef";
24
+ import useShallowStable from "../../../hooks/useShallowStable";
24
25
  import { jsx as _jsx } from "react/jsx-runtime";
26
+ // 解构默认值写成字面量会每次渲染新建一个数组,进依赖数组就让 memo 恒不命中;提到模块级常量
27
+ var DEFAULT_IN_RANGE_COLOR = ["#8BCCFB", "#75C3FB", "#5AB5F6", "#42AEFA", "#2DA1F5", "#0F89E1", "#056FBB", "#025794", "#0A4089"];
25
28
  var Heatmap = function Heatmap(props) {
26
29
  var className = props.className,
27
30
  style = props.style,
@@ -40,8 +43,12 @@ var Heatmap = function Heatmap(props) {
40
43
  onClick = props.onClick,
41
44
  zeroColor = props.zeroColor,
42
45
  _props$inRangeColor = props.inRangeColor,
43
- inRangeColor = _props$inRangeColor === void 0 ? ["#8BCCFB", "#75C3FB", "#5AB5F6", "#42AEFA", "#2DA1F5", "#0F89E1", "#056FBB", "#025794", "#0A4089"] : _props$inRangeColor,
44
- coreOption = _objectWithoutProperties(props, _excluded);
46
+ inRangeColor = _props$inRangeColor === void 0 ? DEFAULT_IN_RANGE_COLOR : _props$inRangeColor,
47
+ restOption = _objectWithoutProperties(props, _excluded);
48
+ // rest 解构出来的对象每次渲染都是新引用,直接进依赖数组会让 chartOption 的 memo
49
+ // 恒不命中 —— 父组件每渲染一次就重跑一次 setOption(notMerge),动画重播、悬浮态被清掉。
50
+ // useShallowStable 让它回到值语义:内容浅相等就复用同一引用,真变了立刻透出新引用。
51
+ var coreOption = useShallowStable(restOption);
45
52
  var chartRef = useRef(null);
46
53
  var chartInstanceRef = useRef(null);
47
54
  // Defers `echarts.init` until the container has a box — see the hook for why
@@ -17,6 +17,7 @@ import { buildCartesianSeriesOptions, createDefaultCategoryXAxis, createDefaultV
17
17
  import { resolveChartChrome } from "../_utils/chartTheme";
18
18
  import useIsDark from "../../../hooks/useIsDark";
19
19
  import useLatestRef from "../../../hooks/useLatestRef";
20
+ import useShallowStable from "../../../hooks/useShallowStable";
20
21
  import { jsx as _jsx } from "react/jsx-runtime";
21
22
  var ChartLine = function ChartLine(props) {
22
23
  var className = props.className,
@@ -45,7 +46,11 @@ var ChartLine = function ChartLine(props) {
45
46
  legendVisibleCount = _props$legendVisibleC === void 0 ? 8 : _props$legendVisibleC,
46
47
  _props$legendScrollIn = props.legendScrollInterval,
47
48
  legendScrollInterval = _props$legendScrollIn === void 0 ? 1500 : _props$legendScrollIn,
48
- coreOption = _objectWithoutProperties(props, _excluded);
49
+ restOption = _objectWithoutProperties(props, _excluded);
50
+ // rest 解构出来的对象每次渲染都是新引用,直接进依赖数组会让 chartOption 的 memo
51
+ // 恒不命中 —— 父组件每渲染一次就重跑一次 setOption(notMerge),动画重播、悬浮态被清掉。
52
+ // useShallowStable 让它回到值语义:内容浅相等就复用同一引用,真变了立刻透出新引用。
53
+ var coreOption = useShallowStable(restOption);
49
54
  var chartRef = useRef(null);
50
55
  var chartInstanceRef = useRef(null);
51
56
  // Defers `echarts.init` until the container has a box — see the hook for why
@@ -9,7 +9,15 @@ import { useMouseOverHandler, useGlobalOutHandler } from "./_hooks";
9
9
  import { getPie3DOption } from "./_utils/option";
10
10
  import styles from "../../index.module.scss";
11
11
  import { useLatestRef } from "../../../../hooks/useLatestRef";
12
+ import useShallowStable from "../../../../hooks/useShallowStable";
12
13
  import { jsx as _jsx } from "react/jsx-runtime";
14
+ // 解构默认值写成字面量会每次渲染新建一个对象,进依赖数组就让 memo 恒不命中;提到模块级常量
15
+ var DEFAULT_TOOLTIP = {
16
+ show: false
17
+ };
18
+ var DEFAULT_LABEL = {
19
+ show: true
20
+ };
13
21
  var ChartPie3D = function ChartPie3D(props) {
14
22
  var className = props.className,
15
23
  style = props.style,
@@ -33,18 +41,18 @@ var ChartPie3D = function ChartPie3D(props) {
33
41
  _props$yOffset = props.yOffset,
34
42
  yOffset = _props$yOffset === void 0 ? -0.2 : _props$yOffset,
35
43
  _props$tooltip = props.tooltip,
36
- tooltip = _props$tooltip === void 0 ? {
37
- show: false
38
- } : _props$tooltip,
44
+ tooltip = _props$tooltip === void 0 ? DEFAULT_TOOLTIP : _props$tooltip,
39
45
  _props$label = props.label,
40
- label = _props$label === void 0 ? {
41
- show: true
42
- } : _props$label,
46
+ label = _props$label === void 0 ? DEFAULT_LABEL : _props$label,
43
47
  _props$enableMouseCon = props.enableMouseControl,
44
48
  enableMouseControl = _props$enableMouseCon === void 0 ? false : _props$enableMouseCon,
45
49
  onChart = props.onChart,
46
50
  onClick = props.onClick,
47
- coreOption = _objectWithoutProperties(props, _excluded);
51
+ restOption = _objectWithoutProperties(props, _excluded);
52
+ // rest 解构出来的对象每次渲染都是新引用,直接进依赖数组会让 chartOption 的 memo
53
+ // 恒不命中 —— 父组件每渲染一次就重跑一次 setOption(notMerge),动画重播、悬浮态被清掉。
54
+ // useShallowStable 让它回到值语义:内容浅相等就复用同一引用,真变了立刻透出新引用。
55
+ var coreOption = useShallowStable(restOption);
48
56
  var chartRef = useRef(null);
49
57
  var chartInstanceRef = useRef(null);
50
58
  // Defers `echarts.init` until the container has a box — see the hook for why
@@ -20,7 +20,10 @@ import { autoScrollLegend } from "../chartUtils";
20
20
  import styles from "../index.module.scss";
21
21
  import ChartPie3D from "./Pie3D";
22
22
  import { useLatestRef } from "../../../hooks/useLatestRef";
23
+ import useShallowStable from "../../../hooks/useShallowStable";
23
24
  import { jsx as _jsx } from "react/jsx-runtime";
25
+ // 解构默认值写成字面量会每次渲染新建一个数组,进依赖数组就让 memo 恒不命中;提到模块级常量
26
+ var EMPTY_EXTEND_SERIES = [];
24
27
  var ChartPie = function ChartPie(props) {
25
28
  var className = props.className,
26
29
  style = props.style,
@@ -32,7 +35,7 @@ var ChartPie = function ChartPie(props) {
32
35
  title = props.title,
33
36
  onChart = props.onChart,
34
37
  _props$extendSeries = props.extendSeries,
35
- extendSeries = _props$extendSeries === void 0 ? [] : _props$extendSeries,
38
+ extendSeries = _props$extendSeries === void 0 ? EMPTY_EXTEND_SERIES : _props$extendSeries,
36
39
  onClick = props.onClick,
37
40
  _props$enableLegendAu = props.enableLegendAutoScroll,
38
41
  enableLegendAutoScroll = _props$enableLegendAu === void 0 ? false : _props$enableLegendAu,
@@ -48,7 +51,11 @@ var ChartPie = function ChartPie(props) {
48
51
  spanAngle = _props$spanAngle === void 0 ? 180 : _props$spanAngle,
49
52
  center = props.center,
50
53
  radius = props.radius,
51
- coreOption = _objectWithoutProperties(props, _excluded);
54
+ restOption = _objectWithoutProperties(props, _excluded);
55
+ // rest 解构出来的对象每次渲染都是新引用,直接进依赖数组会让 chartOption 的 memo
56
+ // 恒不命中 —— 父组件每渲染一次就重跑一次 setOption(notMerge),动画重播、悬浮态被清掉。
57
+ // useShallowStable 让它回到值语义:内容浅相等就复用同一引用,真变了立刻透出新引用。
58
+ var coreOption = useShallowStable(restOption);
52
59
  var chartRef = useRef(null);
53
60
  var chartInstanceRef = useRef(null);
54
61
  // Defers `echarts.init` until the container has a box — see the hook for why
@@ -11,7 +11,10 @@ import * as echarts from "echarts";
11
11
  import useContainerReady from "../_hooks/useContainerReady";
12
12
  import React, { useCallback, useEffect, useMemo, useRef } from "react";
13
13
  import styles from "../index.module.scss";
14
+ import useShallowStable from "../../../hooks/useShallowStable";
14
15
  import { jsx as _jsx } from "react/jsx-runtime";
16
+ // 解构默认值写成字面量会每次渲染新建一个数组,进依赖数组就让 memo 恒不命中;提到模块级常量
17
+ var DEFAULT_COLOR = ["#00FFA3", "#00FFA3"];
15
18
  var Polar = function Polar(props) {
16
19
  var className = props.className,
17
20
  style = props.style,
@@ -26,8 +29,12 @@ var Polar = function Polar(props) {
26
29
  textStyle = props.textStyle,
27
30
  seriesData = props.seriesData,
28
31
  _props$color = props.color,
29
- color = _props$color === void 0 ? ["#00FFA3", "#00FFA3"] : _props$color,
30
- coreOption = _objectWithoutProperties(props, _excluded);
32
+ color = _props$color === void 0 ? DEFAULT_COLOR : _props$color,
33
+ restOption = _objectWithoutProperties(props, _excluded);
34
+ // rest 解构出来的对象每次渲染都是新引用,直接进依赖数组会让 chartOption 的 memo
35
+ // 恒不命中 —— 父组件每渲染一次就重跑一次 setOption(notMerge),动画重播、悬浮态被清掉。
36
+ // useShallowStable 让它回到值语义:内容浅相等就复用同一引用,真变了立刻透出新引用。
37
+ var coreOption = useShallowStable(restOption);
31
38
  var chartRef = useRef(null);
32
39
  var chartInstanceRef = useRef(null);
33
40
  // Defers `echarts.init` until the container has a box — see the hook for why
@@ -17,6 +17,7 @@ import * as echarts from "echarts";
17
17
  import useContainerReady from "../_hooks/useContainerReady";
18
18
  import React, { useCallback, useEffect, useMemo, useRef } from "react";
19
19
  import styles from "../index.module.scss";
20
+ import useShallowStable from "../../../hooks/useShallowStable";
20
21
 
21
22
  /** Single-indicator tooltip trigger mode
22
23
  * - `point` triggers only when hovering data points/lines (native echarts item trigger)
@@ -38,7 +39,11 @@ var Radar = function Radar(props) {
38
39
  singleIndicatorTooltipProp = _props$singleIndicato === void 0 ? false : _props$singleIndicato,
39
40
  singleIndicatorMode = props.singleIndicatorMode,
40
41
  singleIndicatorHoverFill = props.singleIndicatorHoverFill,
41
- coreOption = _objectWithoutProperties(props, _excluded);
42
+ restOption = _objectWithoutProperties(props, _excluded);
43
+ // rest 解构出来的对象每次渲染都是新引用,直接进依赖数组会让 chartOption 的 memo
44
+ // 恒不命中 —— 父组件每渲染一次就重跑一次 setOption(notMerge),动画重播、悬浮态被清掉。
45
+ // useShallowStable 让它回到值语义:内容浅相等就复用同一引用,真变了立刻透出新引用。
46
+ var coreOption = useShallowStable(restOption);
42
47
  var chartRef = useRef(null);
43
48
  var chartInstanceRef = useRef(null);
44
49
  // Defers `echarts.init` until the container has a box — see the hook for why
@@ -0,0 +1,32 @@
1
+ /**
2
+ * 把一个**内容没变、但每次渲染都新建**的对象收敛成**引用恒定**的对象:
3
+ * 浅比较(自有键 + `Object.is` 比值)相等就继续返回上一次那个引用。
4
+ *
5
+ * 用途只有一个:让它可以直接进 `useMemo` / `useEffect` 的依赖数组。
6
+ *
7
+ * React 的依赖数组按 `Object.is` 比引用,所以依赖里只要混进一个「每次渲染都新建
8
+ * 的对象」,memo 就**恒不命中**、effect 就**每渲染必重跑**。组件内部最容易出现
9
+ * 这种对象的地方是 rest 解构:
10
+ *
11
+ * ```tsx
12
+ * const { className, style, ...coreOption } = props; // coreOption 每次都是新对象
13
+ * const option = useMemo(() => ({ ...coreOption }), [coreOption]); // 永远不命中
14
+ * ```
15
+ *
16
+ * 消费方就算把每一个 prop 都 memo 好,也躲不掉——新对象是组件自己建的。
17
+ * 正确写法是让这个对象回到值语义:
18
+ *
19
+ * ```tsx
20
+ * const { className, style, ...restOption } = props;
21
+ * const coreOption = useShallowStable(restOption); // 内容不变 → 引用不变
22
+ * ```
23
+ *
24
+ * 注意这**不是**「缓存结果跳过副作用」:memo 该重算时照样重算、effect 该重跑时
25
+ * 照样重跑——只要 rest 里任何一个值真的变了,浅比较就不相等,新引用立刻透出去。
26
+ *
27
+ * 渲染期间读写 ref 的安全性:并发渲染下被丢弃的那次渲染可能已经把 ref 换成了它
28
+ * 自己的对象,但那个对象与当次 props 浅相等,所以后续渲染拿到的引用**内容永远
29
+ * 与当前 props 一致**,不会读到过期值。
30
+ */
31
+ export declare function useShallowStable<T extends object>(value: T): T;
32
+ export default useShallowStable;
@@ -0,0 +1,54 @@
1
+ import { useRef } from "react";
2
+
3
+ /**
4
+ * 把一个**内容没变、但每次渲染都新建**的对象收敛成**引用恒定**的对象:
5
+ * 浅比较(自有键 + `Object.is` 比值)相等就继续返回上一次那个引用。
6
+ *
7
+ * 用途只有一个:让它可以直接进 `useMemo` / `useEffect` 的依赖数组。
8
+ *
9
+ * React 的依赖数组按 `Object.is` 比引用,所以依赖里只要混进一个「每次渲染都新建
10
+ * 的对象」,memo 就**恒不命中**、effect 就**每渲染必重跑**。组件内部最容易出现
11
+ * 这种对象的地方是 rest 解构:
12
+ *
13
+ * ```tsx
14
+ * const { className, style, ...coreOption } = props; // coreOption 每次都是新对象
15
+ * const option = useMemo(() => ({ ...coreOption }), [coreOption]); // 永远不命中
16
+ * ```
17
+ *
18
+ * 消费方就算把每一个 prop 都 memo 好,也躲不掉——新对象是组件自己建的。
19
+ * 正确写法是让这个对象回到值语义:
20
+ *
21
+ * ```tsx
22
+ * const { className, style, ...restOption } = props;
23
+ * const coreOption = useShallowStable(restOption); // 内容不变 → 引用不变
24
+ * ```
25
+ *
26
+ * 注意这**不是**「缓存结果跳过副作用」:memo 该重算时照样重算、effect 该重跑时
27
+ * 照样重跑——只要 rest 里任何一个值真的变了,浅比较就不相等,新引用立刻透出去。
28
+ *
29
+ * 渲染期间读写 ref 的安全性:并发渲染下被丢弃的那次渲染可能已经把 ref 换成了它
30
+ * 自己的对象,但那个对象与当次 props 浅相等,所以后续渲染拿到的引用**内容永远
31
+ * 与当前 props 一致**,不会读到过期值。
32
+ */
33
+ export function useShallowStable(value) {
34
+ var ref = useRef(value);
35
+ if (!shallowEqual(ref.current, value)) {
36
+ ref.current = value;
37
+ }
38
+ return ref.current;
39
+ }
40
+ function shallowEqual(a, b) {
41
+ if (Object.is(a, b)) return true;
42
+ var aKeys = Object.keys(a);
43
+ var bKeys = Object.keys(b);
44
+ if (aKeys.length !== bKeys.length) return false;
45
+ for (var _i = 0, _aKeys = aKeys; _i < _aKeys.length; _i++) {
46
+ var key = _aKeys[_i];
47
+ if (!Object.prototype.hasOwnProperty.call(b, key)) return false;
48
+ if (!Object.is(a[key], b[key])) {
49
+ return false;
50
+ }
51
+ }
52
+ return true;
53
+ }
54
+ export default useShallowStable;
@@ -14,6 +14,7 @@ var _cartesian = require("../_utils/cartesian");
14
14
  var _chartTheme = require("../_utils/chartTheme");
15
15
  var _useIsDark = _interopRequireDefault(require("../../../hooks/useIsDark"));
16
16
  var _useLatestRef = _interopRequireDefault(require("../../../hooks/useLatestRef"));
17
+ var _useShallowStable = _interopRequireDefault(require("../../../hooks/useShallowStable"));
17
18
  var _jsxRuntime = require("react/jsx-runtime");
18
19
  function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
19
20
  function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function (e) { return e ? t : r; })(e); }
@@ -43,8 +44,12 @@ const ChartBar = props => {
43
44
  enableLegendAutoScroll = false,
44
45
  legendVisibleCount = 8,
45
46
  legendScrollInterval = 1500,
46
- ...coreOption
47
+ ...restOption
47
48
  } = props;
49
+ // rest 解构出来的对象每次渲染都是新引用,直接进依赖数组会让 chartOption 的 memo
50
+ // 恒不命中 —— 父组件每渲染一次就重跑一次 setOption(notMerge),动画重播、悬浮态被清掉。
51
+ // useShallowStable 让它回到值语义:内容浅相等就复用同一引用,真变了立刻透出新引用。
52
+ const coreOption = (0, _useShallowStable.default)(restOption);
48
53
  const chartRef = (0, _react.useRef)(null);
49
54
  const chartInstanceRef = (0, _react.useRef)(null);
50
55
  // Defers `echarts.init` until the container has a box — see the hook for why
@@ -9,6 +9,7 @@ var _indexModule = _interopRequireDefault(require("../index.module.scss"));
9
9
  var echarts = _interopRequireWildcard(require("echarts"));
10
10
  var _bubble = require("../_utils/bubble");
11
11
  var _useLatestRef = require("../../../hooks/useLatestRef");
12
+ var _useShallowStable = _interopRequireDefault(require("../../../hooks/useShallowStable"));
12
13
  var _jsxRuntime = require("react/jsx-runtime");
13
14
  function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
14
15
  function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function (e) { return e ? t : r; })(e); }
@@ -28,8 +29,12 @@ const Bubble = props => {
28
29
  title,
29
30
  onChart,
30
31
  onClick,
31
- ...coreOption
32
+ ...restOption
32
33
  } = props;
34
+ // rest 解构出来的对象每次渲染都是新引用,直接进依赖数组会让 chartOption 的 memo
35
+ // 恒不命中 —— 父组件每渲染一次就重跑一次 setOption(notMerge),动画重播、悬浮态被清掉。
36
+ // useShallowStable 让它回到值语义:内容浅相等就复用同一引用,真变了立刻透出新引用。
37
+ const coreOption = (0, _useShallowStable.default)(restOption);
33
38
  const chartRef = (0, _react.useRef)(null);
34
39
  const chartInstanceRef = (0, _react.useRef)(null);
35
40
  const resizeObserverRef = (0, _react.useRef)(null);
@@ -9,6 +9,7 @@ var _useContainerReady = _interopRequireDefault(require("../_hooks/useContainerR
9
9
  var _indexModule = _interopRequireDefault(require("../index.module.scss"));
10
10
  var echarts = _interopRequireWildcard(require("echarts"));
11
11
  var _useLatestRef = require("../../../hooks/useLatestRef");
12
+ var _useShallowStable = _interopRequireDefault(require("../../../hooks/useShallowStable"));
12
13
  var _jsxRuntime = require("react/jsx-runtime");
13
14
  function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
14
15
  function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function (e) { return e ? t : r; })(e); }
@@ -18,8 +19,12 @@ const Common = props => {
18
19
  className,
19
20
  style,
20
21
  onChart,
21
- ...coreOption
22
+ ...restOption
22
23
  } = props;
24
+ // rest 解构出来的对象每次渲染都是新引用,直接进依赖数组会让 chartOption 的 memo
25
+ // 恒不命中 —— 父组件每渲染一次就重跑一次 setOption(notMerge),动画重播、悬浮态被清掉。
26
+ // useShallowStable 让它回到值语义:内容浅相等就复用同一引用,真变了立刻透出新引用。
27
+ const coreOption = (0, _useShallowStable.default)(restOption);
23
28
  const chartRef = (0, _react.useRef)(null);
24
29
  const chartInstanceRef = (0, _react.useRef)(null);
25
30
  // Defers `echarts.init` until the container has a box — see the hook for why
@@ -8,6 +8,7 @@ var echarts = _interopRequireWildcard(require("echarts"));
8
8
  var _useContainerReady = _interopRequireDefault(require("../_hooks/useContainerReady"));
9
9
  var _react = _interopRequireWildcard(require("react"));
10
10
  var _indexModule = _interopRequireDefault(require("../index.module.scss"));
11
+ var _useShallowStable = _interopRequireDefault(require("../../../hooks/useShallowStable"));
11
12
  var _jsxRuntime = require("react/jsx-runtime");
12
13
  function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
13
14
  function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function (e) { return e ? t : r; })(e); }
@@ -29,8 +30,12 @@ const Gauge = props => {
29
30
  axisLabel,
30
31
  title,
31
32
  color = "#1675FB",
32
- ...coreSeries
33
+ ...restSeries
33
34
  } = series;
35
+ // rest 解构出来的对象每次渲染都是新引用,直接进依赖数组会让 chartOption 的 memo
36
+ // 恒不命中 —— 父组件每渲染一次就重跑一次 setOption(notMerge),动画重播、悬浮态被清掉。
37
+ // useShallowStable 让它回到值语义:内容浅相等就复用同一引用,真变了立刻透出新引用。
38
+ const coreSeries = (0, _useShallowStable.default)(restSeries);
34
39
  const chartRef = (0, _react.useRef)(null);
35
40
  const chartInstanceRef = (0, _react.useRef)(null);
36
41
  // Defers `echarts.init` until the container has a box — see the hook for why
@@ -12,10 +12,13 @@ var _heatmap = require("../_utils/heatmap");
12
12
  var _chartTheme = require("../_utils/chartTheme");
13
13
  var _useIsDark = _interopRequireDefault(require("../../../hooks/useIsDark"));
14
14
  var _useLatestRef = require("../../../hooks/useLatestRef");
15
+ var _useShallowStable = _interopRequireDefault(require("../../../hooks/useShallowStable"));
15
16
  var _jsxRuntime = require("react/jsx-runtime");
16
17
  function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
17
18
  function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function (e) { return e ? t : r; })(e); }
18
19
  function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != typeof e && "function" != typeof e) return { default: e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && Object.prototype.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n.default = e, t && t.set(e, n), n; }
20
+ // 解构默认值写成字面量会每次渲染新建一个数组,进依赖数组就让 memo 恒不命中;提到模块级常量
21
+ const DEFAULT_IN_RANGE_COLOR = ["#8BCCFB", "#75C3FB", "#5AB5F6", "#42AEFA", "#2DA1F5", "#0F89E1", "#056FBB", "#025794", "#0A4089"];
19
22
  const Heatmap = props => {
20
23
  const {
21
24
  className,
@@ -34,9 +37,13 @@ const Heatmap = props => {
34
37
  onChart,
35
38
  onClick,
36
39
  zeroColor,
37
- inRangeColor = ["#8BCCFB", "#75C3FB", "#5AB5F6", "#42AEFA", "#2DA1F5", "#0F89E1", "#056FBB", "#025794", "#0A4089"],
38
- ...coreOption
40
+ inRangeColor = DEFAULT_IN_RANGE_COLOR,
41
+ ...restOption
39
42
  } = props;
43
+ // rest 解构出来的对象每次渲染都是新引用,直接进依赖数组会让 chartOption 的 memo
44
+ // 恒不命中 —— 父组件每渲染一次就重跑一次 setOption(notMerge),动画重播、悬浮态被清掉。
45
+ // useShallowStable 让它回到值语义:内容浅相等就复用同一引用,真变了立刻透出新引用。
46
+ const coreOption = (0, _useShallowStable.default)(restOption);
40
47
  const chartRef = (0, _react.useRef)(null);
41
48
  const chartInstanceRef = (0, _react.useRef)(null);
42
49
  // Defers `echarts.init` until the container has a box — see the hook for why
@@ -14,6 +14,7 @@ var _cartesian = require("../_utils/cartesian");
14
14
  var _chartTheme = require("../_utils/chartTheme");
15
15
  var _useIsDark = _interopRequireDefault(require("../../../hooks/useIsDark"));
16
16
  var _useLatestRef = _interopRequireDefault(require("../../../hooks/useLatestRef"));
17
+ var _useShallowStable = _interopRequireDefault(require("../../../hooks/useShallowStable"));
17
18
  var _jsxRuntime = require("react/jsx-runtime");
18
19
  function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
19
20
  function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function (e) { return e ? t : r; })(e); }
@@ -43,8 +44,12 @@ const ChartLine = props => {
43
44
  enableLegendAutoScroll = false,
44
45
  legendVisibleCount = 8,
45
46
  legendScrollInterval = 1500,
46
- ...coreOption
47
+ ...restOption
47
48
  } = props;
49
+ // rest 解构出来的对象每次渲染都是新引用,直接进依赖数组会让 chartOption 的 memo
50
+ // 恒不命中 —— 父组件每渲染一次就重跑一次 setOption(notMerge),动画重播、悬浮态被清掉。
51
+ // useShallowStable 让它回到值语义:内容浅相等就复用同一引用,真变了立刻透出新引用。
52
+ const coreOption = (0, _useShallowStable.default)(restOption);
48
53
  const chartRef = (0, _react.useRef)(null);
49
54
  const chartInstanceRef = (0, _react.useRef)(null);
50
55
  // Defers `echarts.init` until the container has a box — see the hook for why
@@ -12,10 +12,18 @@ var _hooks = require("./_hooks");
12
12
  var _option = require("./_utils/option");
13
13
  var _indexModule = _interopRequireDefault(require("../../index.module.scss"));
14
14
  var _useLatestRef = require("../../../../hooks/useLatestRef");
15
+ var _useShallowStable = _interopRequireDefault(require("../../../../hooks/useShallowStable"));
15
16
  var _jsxRuntime = require("react/jsx-runtime");
16
17
  function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
17
18
  function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function (e) { return e ? t : r; })(e); }
18
19
  function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != typeof e && "function" != typeof e) return { default: e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && Object.prototype.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n.default = e, t && t.set(e, n), n; }
20
+ // 解构默认值写成字面量会每次渲染新建一个对象,进依赖数组就让 memo 恒不命中;提到模块级常量
21
+ const DEFAULT_TOOLTIP = {
22
+ show: false
23
+ };
24
+ const DEFAULT_LABEL = {
25
+ show: true
26
+ };
19
27
  const ChartPie3D = props => {
20
28
  const {
21
29
  className,
@@ -30,17 +38,17 @@ const ChartPie3D = props => {
30
38
  minHeight = 1,
31
39
  maxHeight = 10,
32
40
  yOffset = -0.2,
33
- tooltip = {
34
- show: false
35
- },
36
- label = {
37
- show: true
38
- },
41
+ tooltip = DEFAULT_TOOLTIP,
42
+ label = DEFAULT_LABEL,
39
43
  enableMouseControl = false,
40
44
  onChart,
41
45
  onClick,
42
- ...coreOption
46
+ ...restOption
43
47
  } = props;
48
+ // rest 解构出来的对象每次渲染都是新引用,直接进依赖数组会让 chartOption 的 memo
49
+ // 恒不命中 —— 父组件每渲染一次就重跑一次 setOption(notMerge),动画重播、悬浮态被清掉。
50
+ // useShallowStable 让它回到值语义:内容浅相等就复用同一引用,真变了立刻透出新引用。
51
+ const coreOption = (0, _useShallowStable.default)(restOption);
44
52
  const chartRef = (0, _react.useRef)(null);
45
53
  const chartInstanceRef = (0, _react.useRef)(null);
46
54
  // Defers `echarts.init` until the container has a box — see the hook for why
@@ -11,10 +11,13 @@ var _chartUtils = require("../chartUtils");
11
11
  var _indexModule = _interopRequireDefault(require("../index.module.scss"));
12
12
  var _Pie3D = _interopRequireDefault(require("./Pie3D"));
13
13
  var _useLatestRef = require("../../../hooks/useLatestRef");
14
+ var _useShallowStable = _interopRequireDefault(require("../../../hooks/useShallowStable"));
14
15
  var _jsxRuntime = require("react/jsx-runtime");
15
16
  function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
16
17
  function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function (e) { return e ? t : r; })(e); }
17
18
  function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != typeof e && "function" != typeof e) return { default: e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && Object.prototype.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n.default = e, t && t.set(e, n), n; }
19
+ // 解构默认值写成字面量会每次渲染新建一个数组,进依赖数组就让 memo 恒不命中;提到模块级常量
20
+ const EMPTY_EXTEND_SERIES = [];
18
21
  const ChartPie = props => {
19
22
  const {
20
23
  className,
@@ -26,7 +29,7 @@ const ChartPie = props => {
26
29
  series,
27
30
  title,
28
31
  onChart,
29
- extendSeries = [],
32
+ extendSeries = EMPTY_EXTEND_SERIES,
30
33
  onClick,
31
34
  enableLegendAutoScroll = false,
32
35
  legendVisibleCount = 8,
@@ -36,8 +39,12 @@ const ChartPie = props => {
36
39
  spanAngle = 180,
37
40
  center,
38
41
  radius,
39
- ...coreOption
42
+ ...restOption
40
43
  } = props;
44
+ // rest 解构出来的对象每次渲染都是新引用,直接进依赖数组会让 chartOption 的 memo
45
+ // 恒不命中 —— 父组件每渲染一次就重跑一次 setOption(notMerge),动画重播、悬浮态被清掉。
46
+ // useShallowStable 让它回到值语义:内容浅相等就复用同一引用,真变了立刻透出新引用。
47
+ const coreOption = (0, _useShallowStable.default)(restOption);
41
48
  const chartRef = (0, _react.useRef)(null);
42
49
  const chartInstanceRef = (0, _react.useRef)(null);
43
50
  // Defers `echarts.init` until the container has a box — see the hook for why
@@ -8,10 +8,13 @@ var echarts = _interopRequireWildcard(require("echarts"));
8
8
  var _useContainerReady = _interopRequireDefault(require("../_hooks/useContainerReady"));
9
9
  var _react = _interopRequireWildcard(require("react"));
10
10
  var _indexModule = _interopRequireDefault(require("../index.module.scss"));
11
+ var _useShallowStable = _interopRequireDefault(require("../../../hooks/useShallowStable"));
11
12
  var _jsxRuntime = require("react/jsx-runtime");
12
13
  function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
13
14
  function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function (e) { return e ? t : r; })(e); }
14
15
  function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != typeof e && "function" != typeof e) return { default: e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && Object.prototype.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n.default = e, t && t.set(e, n), n; }
16
+ // 解构默认值写成字面量会每次渲染新建一个数组,进依赖数组就让 memo 恒不命中;提到模块级常量
17
+ const DEFAULT_COLOR = ["#00FFA3", "#00FFA3"];
15
18
  const Polar = props => {
16
19
  const {
17
20
  className,
@@ -26,9 +29,13 @@ const Polar = props => {
26
29
  title2Style,
27
30
  textStyle,
28
31
  seriesData,
29
- color = ["#00FFA3", "#00FFA3"],
30
- ...coreOption
32
+ color = DEFAULT_COLOR,
33
+ ...restOption
31
34
  } = props;
35
+ // rest 解构出来的对象每次渲染都是新引用,直接进依赖数组会让 chartOption 的 memo
36
+ // 恒不命中 —— 父组件每渲染一次就重跑一次 setOption(notMerge),动画重播、悬浮态被清掉。
37
+ // useShallowStable 让它回到值语义:内容浅相等就复用同一引用,真变了立刻透出新引用。
38
+ const coreOption = (0, _useShallowStable.default)(restOption);
32
39
  const chartRef = (0, _react.useRef)(null);
33
40
  const chartInstanceRef = (0, _react.useRef)(null);
34
41
  // Defers `echarts.init` until the container has a box — see the hook for why
@@ -8,6 +8,7 @@ var echarts = _interopRequireWildcard(require("echarts"));
8
8
  var _useContainerReady = _interopRequireDefault(require("../_hooks/useContainerReady"));
9
9
  var _react = _interopRequireWildcard(require("react"));
10
10
  var _indexModule = _interopRequireDefault(require("../index.module.scss"));
11
+ var _useShallowStable = _interopRequireDefault(require("../../../hooks/useShallowStable"));
11
12
  var _jsxRuntime = require("react/jsx-runtime");
12
13
  function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
13
14
  function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function (e) { return e ? t : r; })(e); }
@@ -30,8 +31,12 @@ const Radar = props => {
30
31
  singleIndicatorTooltip: singleIndicatorTooltipProp = false,
31
32
  singleIndicatorMode,
32
33
  singleIndicatorHoverFill,
33
- ...coreOption
34
+ ...restOption
34
35
  } = props;
36
+ // rest 解构出来的对象每次渲染都是新引用,直接进依赖数组会让 chartOption 的 memo
37
+ // 恒不命中 —— 父组件每渲染一次就重跑一次 setOption(notMerge),动画重播、悬浮态被清掉。
38
+ // useShallowStable 让它回到值语义:内容浅相等就复用同一引用,真变了立刻透出新引用。
39
+ const coreOption = (0, _useShallowStable.default)(restOption);
35
40
  const chartRef = (0, _react.useRef)(null);
36
41
  const chartInstanceRef = (0, _react.useRef)(null);
37
42
  // Defers `echarts.init` until the container has a box — see the hook for why