It seems a common technic to use PureComponent to improve rendering perf in React. However, it seems not the case when using PureComponent who has children as props.
class App extends React.PureComponent {
render() {
console.log('re-render')
return <div>{this.props.children}</div>
}
}
const render = () => {
ReactDOM.render(
<App>
<div />
</App>,
document.getElementById('app')
)
setTimeout(render, 1000)
}
render()
The result is that console keeps logging 're-render' every 1s. It seems the children(<div />
) is the only prop of above App
component and never changes, why App still gets re-rendered?
Note: in case of any confusion, the question is the same as, why SCU(shouldComponentUpdate) hook of PureComponent above return true since no props seems changed?
React Components and Children In React, a component can have one, many, or no children.
This doesn't only mean the component's render function will be called, but also that all its subsequent child components will re-render, regardless of whether their props have changed or not.
If your React component's render() function renders the same result given the same props and state, you can use React. PureComponent for a performance boost in some cases.
memo() If you're using a React class component you can use the shouldComponentUpdate method or a React. PureComponent class extension to prevent a component from re-rendering.
What happen here is you're actually calling ReactDOM.render()
, Page (or App, I suppose you have a typo here) component is gonna trigger its render()
function regardless of using Component
or PureComponent
.
The way PureComponent can help to reduce unnecessary rendering is when there is a prop change, PureComponent will do a shallow comparison on this.props
and nextProps
to determine if this PureComponent needs to call render()
.
I just made this example for you:
class App extends React.PureComponent {
state = {value: 0}
componentDidMount() {
setInterval(() => {
this.setState({value: Math.random()})
}, 1000)
}
render() {
return (
<div>
<PureChild value="fixed value"/>
<ImpureChild value="fixed value"/>
</div>
)
}
}
class PureChild extends React.PureComponent {
render() {
console.log('rendering PureChild')
return <div>{this.props.value}</div>
}
}
class ImpureChild extends React.Component {
render() {
console.log('rendering ImpureChild')
return <div>{this.props.value}</div>
}
}
Pay attention to this few things:
<App />
change value
state, thus it re-renders, causing all its children to re-render as well.<PureChild />
is a PureComponent, it does a shallow comparison on its old props and incoming new props, and notices both props are "fixed value"
, and therefore it doesn't trigger render!If you run this code and open up console, you'll see only 'rendering ImpureChild' every 1s, but 'rendering PureChild' will only appear once.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With