I have a Canvas component, which looks approximately like this:
class Canvas extends React.Component{
saveRef = node => {
this._canvas = node;
}
shouldComponentUpdate(){
/*I will never re-render this component*/
return false;
}
componentWillReceiveProps( nextProps ){
/*Here I do manipulations with this._ctx, when new props come*/
}
render(){
return (
<canvas ref={this.saveRef} />
);
}
componentDidMount(){
this._ctx = this._canvas.getContext( "2d" );
}
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
React community began to deprecate componentWillReceiveProps
in order to replace it with getDerivedStateFromProps
. I can use componentDidUpdate
to perform my drawings, but then I need to remove shouldComponentUpdate
and I will have a lot of useless render calls. What is the correct performant way to update my component in react 16.3, when new props come?
The three phases are: Mounting, Updating, and Unmounting.
componentDidUpdate() This method gets invoked immediately after the component is updated and re-rendered. It receives the prevState and prevProps as parameters and can also access the newly changed state or props.
componentDidUpdate() A most common use case would be, updating the DOM in response to prop or state changes.
In this article, we are going to see how to execute a function if the props passed to the component is updated in the DOM tree. This method is used during the updating phase of the React lifecycle. This function is generally called if the props passed to the component change.
Use componentDidUpdate
for DOM manipulations like this. A shouldComponentUpdate
won’t really make a difference for a component with a single child that always has the same props. So you should be able to remove it without a significant difference in performance.
If you've profiled the application and determined that in this particular case it does make a difference, you can hoist the element into constructor.
This way React will skip over it completely (which effectively works the same way as shouldComponentUpdate
):
class Canvas extends React.Component {
constructor(props) {
super(props);
this._ctx = null;
this._child = <canvas ref={node => {
this._ctx = node ? node.getContext('2d') : null
} />;
}
componentDidUpdate(prevProps){
// Manipulate this._ctx here
}
render() {
// A constant element tells React to never re-render
return this._child;
}
}
You could also split it into two components:
class Canvas extends React.Component {
saveContext = ctx => {
this._ctx = ctx;
}
componentDidUpdate(prevProps){
// Manipulate this._ctx here
}
render() {
return <PureCanvas contextRef={this.saveContext} />;
}
}
class PureCanvas extends React.Component {
shouldComponentUpdate() {
return false;
}
render() {
return (
<canvas
ref={node => node ? this.props.contextRef(node.getContext('2d') : null)}
/>;
}
}
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