What is correct lifecycle method in React 16.3 to update canvas from props?
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)} />; }}
I found this because I had a sort of similar problem but not completely the same. The solution that works for me is just to put all the relevant code in shouldComponentUpdate
:
(the if
statement used to be in componentWillReceiveProps
)
shouldComponentUpdate (nextProps, nextState) { // no more random renders if ( (nextProps.nightMode !== this.props.nightMode) || (nextProps.language !== this.props.language) ) { this.props.setRefresh(true) // setTimeout means after current operation setTimeout(() => this.props.setRefresh(false), 1) // so loading will show for longer than 1ms } return this.props.refresh !== nextProps.refresh }