【问题标题】:How to prevent react from re-rendering the whole component?如何防止 react 重新渲染整个组件?
【发布时间】:2017-06-05 09:44:26
【问题描述】:

我从here 改编了以下组件定义,如下所示。但是,与示例不同,每次我在组件上移动鼠标时都会重新渲染组件。

重新渲染非常明显:

有人知道为什么会这样吗?

import React, { Component } from 'react';
import { PieChart, Pie, Sector } from 'recharts';
import { Segment, Header, Dimmer, Loader, Grid } from 'semantic-ui-react';

const renderActiveShape = (props) => {

const RADIAN = Math.PI / 180;
const { cx, cy, midAngle, innerRadius, outerRadius, startAngle, endAngle,
    fill, payload, percent, value } = 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) * 22;
const ey = my;
const textAnchor = cos >= 0 ? 'start' : 'end';

return (
    <g>
        <text x={cx} y={cy} dy={8} textAnchor="middle" fill={fill}>{payload.name}</text>
        <Sector
            cx={cx}
            cy={cy}
            innerRadius={innerRadius}
            outerRadius={outerRadius}
            startAngle={startAngle}
            endAngle={endAngle}
            fill={fill}
            />
        <Sector
            cx={cx}
            cy={cy}
            startAngle={startAngle}
            endAngle={endAngle}
            innerRadius={outerRadius + 6}
            outerRadius={outerRadius + 10}
            fill={fill}
            />
        <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 x={ex + (cos >= 0 ? 1 : -1) * 12} y={ey} textAnchor={textAnchor} fill="#333">{`PV ${value}`}</text>
        <text x={ex + (cos >= 0 ? 1 : -1) * 12} y={ey} dy={18} textAnchor={textAnchor} fill="#999">
            {`(Rate ${(percent * 100).toFixed(2)}%)`}
        </text>
    </g>
);
};

export default class TwoLevelPie extends Component {

constructor(props) {
    super(props);
    this.state = { activeIndex: 0 }
    this.onPieEnter = this.onPieEnter.bind(this);
}

onPieEnter(data, index) {
    this.setState({
        activeIndex: index
    });
}

render() {

    const data = [{ name: 'Group A', value: 400 }, { name: 'Group B', value: 300 },
    { name: 'Group C', value: 300 }, { name: 'Group D', value: 200 }];

    return (
        <Segment inverted>
            <PieChart width={800} height={400} onMouseEnter={this.onPieEnter}>
                <Pie
                    activeIndex={this.state.activeIndex}
                    activeShape={renderActiveShape}
                    data={data}
                    cx={300}
                    cy={200}
                    innerRadius={60}
                    outerRadius={80}
                    fill="#8884d8" />
            </PieChart>
        </Segment>
    );
}
}

【问题讨论】:

  • 如果您将代码设为runnable on-site,它可能会帮助您获得好的答案。
  • 不知道谢谢我现在试试。
  • 也许这与您每次鼠标悬停时都会更改状态有关 (onPieEnter)?
  • 是的,但是这个例子是如何工作的? @DimitrisKaragiannis
  • @Cemre 我在我的开发工具中看不到它的反应结构。您确定即使将鼠标悬停在同一扇区上也不会重新渲染?即使有,你也不会注意到。

标签: javascript reactjs ecmascript-6


【解决方案1】:

定义为函数的纯组件总是会重新渲染。

将组件转换为类并防止shouldComponentUpdate()中的重新渲染返回false。

签名是shouldComponentUpdate(nextProps, nextState)。比如说,你通过验证组件的参数没有改变来防止重新渲染:

shouldComponentUpdate(nextProps, nextState){
   return !equals(nextProps, this.props); // equals() is your implementation
}

【讨论】:

  • “定义为函数的纯组件将始终重新渲染”这是正确的。新道具传递下来的那一刻,它会重新渲染。
  • 这个equals来自哪里?
  • @JacobIRR 我也想知道。
  • @ZeroDarkThirty @JacobIRR equals() 是您必须实施的方法。它应该定义你的平等“版本”。
  • 关于“定义为函数的纯组件将始终重新渲染”-> 在 React 16.6 中,您可以将它们包装在 React.memo() 中以避免这种情况(除非属性明显改变)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2019-12-05
  • 1970-01-01
  • 2020-03-27
  • 1970-01-01
  • 2020-03-18
  • 2021-05-03
  • 2021-02-14
相关资源
最近更新 更多