如何防止 react 重新渲染整个组件?

Posted

技术标签:

【中文标题】如何防止 react 重新渲染整个组件?【英文标题】:How to prevent react from re-rendering the whole component? 【发布时间】: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,$syL$mx,$myL$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 我在我的开发工具中看不到它的反应结构。您确定即使将鼠标悬停在同一扇区上也不会重新渲染?即使有,你也不会注意到。 【参考方案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() 中以避免这种情况(除非属性明显改变)

以上是关于如何防止 react 重新渲染整个组件?的主要内容,如果未能解决你的问题,请参考以下文章

React:如何防止在`map`中重新渲染子组件?

如何防止我的功能组件使用 React 备忘录或 React 钩子重新渲染?

React Hook 功能组件防止重新渲染

如何防止扩展的 React-Table 行在重新渲染时折叠?

React 限制渲染次数以防止无限循环...重新渲染次数过多

React hooks 功能组件防止在状态更新时重新渲染