【问题标题】:Recharts custom label render every time when mouse over每次鼠标悬停时重新绘制自定义标签
【发布时间】:2021-05-29 12:06:25
【问题描述】:

我为 PieChart 创建自定义标签

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 方法。

如上图,当鼠标悬停在红色、蓝色或灰色区域时,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

【问题讨论】:

    标签: reactjs recharts


    【解决方案1】:

    我认为查看沙盒的主要问题是,当您将MemoComponent 传递给Pie 组件的label 属性时,您仍在使用MemoComponent,就好像它是常规函数一样,而不是组件.

    你这样做:

    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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-09-18
      • 1970-01-01
      • 2011-09-01
      • 1970-01-01
      • 2020-02-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多