React 16.3 中从 props 更新 canvas 的正确生命周期方法是什么?
What is correct lifecycle method in React 16.3 to update canvas from props?
我有一个 Canvas 组件,大致如下所示:
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 社区开始弃用 componentWillReceiveProps
,以便用 getDerivedStateFromProps
取而代之。我可以使用 componentDidUpdate
来执行我的绘图,但是我需要删除 shouldComponentUpdate
并且我会有很多无用的渲染调用。当新道具出现时,在 React 16.3 中更新我的组件的正确性能方式是什么?
使用 componentDidUpdate
进行这样的 DOM 操作。 shouldComponentUpdate
对于只有一个始终具有相同 props 的子组件的组件来说不会有什么不同。所以你应该能够在性能上没有显着差异的情况下删除它。
如果您分析了该应用程序并确定在这种特殊情况下它确实有所作为,您可以提升该元素进入构造函数。
这样 React 将完全跳过它(这与 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;
}
}
您也可以将其拆分为两个部分:
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)}
/>;
}
}
我发现这个是因为我遇到了类似但不完全相同的问题。对我有用的解决方案就是将所有相关代码放入 shouldComponentUpdate
:
(if
语句曾经在 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
}
我有一个 Canvas 组件,大致如下所示:
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 社区开始弃用 componentWillReceiveProps
,以便用 getDerivedStateFromProps
取而代之。我可以使用 componentDidUpdate
来执行我的绘图,但是我需要删除 shouldComponentUpdate
并且我会有很多无用的渲染调用。当新道具出现时,在 React 16.3 中更新我的组件的正确性能方式是什么?
使用 componentDidUpdate
进行这样的 DOM 操作。 shouldComponentUpdate
对于只有一个始终具有相同 props 的子组件的组件来说不会有什么不同。所以你应该能够在性能上没有显着差异的情况下删除它。
如果您分析了该应用程序并确定在这种特殊情况下它确实有所作为,您可以提升该元素进入构造函数。
这样 React 将完全跳过它(这与 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;
}
}
您也可以将其拆分为两个部分:
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)}
/>;
}
}
我发现这个是因为我遇到了类似但不完全相同的问题。对我有用的解决方案就是将所有相关代码放入 shouldComponentUpdate
:
(if
语句曾经在 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
}