每次鼠标悬停时重新绘制自定义标签渲染

问题描述

我为饼图创建自定义标签

CustomLabel.js

const renderCustomizedLabel = (props,centerText) => {
    console.log("rendered")
    return (
        <g>...</g>
    );
};

export default renderCustomizedLabel;

CustomPieChart.js

export default class Example extends PureComponent {
    constructor(props){
        super(props);
    }
    render() {
        return (
            <ResponsiveContainer width="100%" aspect={2}>
                <PieChart width={600} height={600}>
                    <Pie  
                     data={this.props.data} 
                     dataKey="value" 
                     nameKey="name" 
                     cx="50%" cy="50%" innerRadius={80} outerRadius={90}
                     label={(a)=>CustomPieChartLabel(a,this.props.centerText)}>
                     {this.props.data.map((entry,index) => (<Cell key={`cell-${index}`} fill={entry.color} />))}
                     </Pie>
                </PieChart>
             </ResponsiveContainer> 
        );
    }
}

问题

每次将鼠标悬停在单元格上时,renderCustomizedLabel 都会工作并为每个数据渲染。

在上面的代码中,我没有使用任何 onMouseMove、onMouSEOver、onMouseEnter 方法

enter image description here

如上图所示,当鼠标悬停在红色、蓝色或灰色区域时,console.log("rendered") 工作 3 次。

为了解决这个问题,我尝试使用 React.memo

CustomLabelWithMemo.js

const MemoComponent = React.memo(function renderCustomizedLabel(props) {
    console.log("rendered")
    return (
        <g>...</g>
    );
});

export default MemoComponent

但它给了我一个错误

TypeError: Object(...) 不是函数

我该如何解决这个问题?

转载链接 CodeSandBox

解决方法

我认为查看沙箱的主要问题是,在将 MemoComponent 传递给 label Pie 组件。

你这样做:

label={(a) => CustomPieChartLabel(a,this.props.centerText)}

相反,您可以这样做:

label={<CustomPieChartLabel centerText={this.props.centerText} />}

我还稍微调整了您的 CustomPieChartLabel.js 文件:

import React from "react";

const RADIAN = Math.PI / 180;

const renderCustomizedLabel = (props) => {
  console.log("rendered");
  const {
    cx,cy,midAngle,outerRadius,fill,payload,percent,value,centerText
  } = props;
  const sin = Math.sin(-RADIAN * midAngle);
  const cos = Math.cos(-RADIAN * midAngle);
  const sx = cx + (outerRadius + 10) * cos;
  const sy = cy + (outerRadius + 10) * sin;
  const mx = cx + (outerRadius + 30) * cos;
  const my = cy + (outerRadius + 30) * sin;
  const ex = mx + (cos >= 0 ? 1 : -1) * 30;
  const ey = my;
  const textAnchor = cos >= 0 ? "start" : "end";
  return (
    <g>
      <text x={cx} y={cy} textAnchor="middle" fill={fill}>
        {centerText.title}
      </text>
      <text x={cx} y={cy} dy={20} textAnchor="middle" fill={fill}>
        {centerText.value}
      </text>

      <path
        d={`M${sx},${sy}L${mx},${my}L${ex},${ey}`}
        stroke={fill}
        fill="none"
      />
      <circle cx={ex} cy={ey} r={2} fill={fill} stroke="none" />
      <text
        style={{ fontWeight: "bold" }}
        x={ex + (cos >= 0 ? 1 : -1) * 12}
        y={ey}
        textAnchor={textAnchor}
        fill={fill}
      >
        {payload.name}
      </text>
      <text
        x={ex + (cos >= 0 ? 1 : -1) * 12}
        y={ey}
        dy={18}
        textAnchor={textAnchor}
        fill="#999"
      >
        {value}
      </text>
    </g>
  );
};

const CustomPieChartLabel = React.memo(renderCustomizedLabel);

export default CustomPieChartLabel;

Sandbox example

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...