【发布时间】:2019-02-01 20:35:58
【问题描述】:
在网上阅读了一堆关于shouldComponentUpdate 和render 的文章后,我想仔细检查在重新渲染组件(调用render 方法)和调用shouldComponentUpdate 时是否正确。
React 文档(以及数十篇文章说)shouldComponentUpdate 仅在收到新道具或有新状态时调用。但乍一看,PureComponent 似乎也是如此……
为了调查它,我编写了示例应用程序:
- 父组件
import React, { Component } from 'react';
import './App.css';
import Hello from './Hello';
class App extends Component {
objWithName = { name: 'World' };
state = {
date: Date.now()
}
componentDidMount() {
setInterval(() => {
this.setState({ date: Date.now() });
}, 2000);
}
render() {
return (
<div className="App">
<p>Rendering timestamp {this.state.date}</p>
<Hello name={this.objWithName} />
</div>
);
}
}
export default App;
- 子组件
import React from 'react';
export default class Hello extends React.Component {
shouldComponentUpdate() {
console.log('shouldComponentUpdate called');
return true;
}
render() {
console.log('render called');
return <p>Hello {this.props.name.name}</p>
}
}
所以我的第一个问题是:这是完全正确的吗?我的意思是:在上面的代码 sn-ps 中,setInterval 中的父组件调用setState 只是为了触发它的更新,但这种状态在任何地方都没有使用。之后,子组件被重新渲染(render 被调用)和shouldComponentUpdate 被调用,即使他没有任何改变(它没有收到任何新的道具,也没有状态)。我在 React 文档中没有找到对这种行为的任何解释,所以我不确定它是如何工作的。更重要的是,如果该子组件在(仅渲染静态字符串)处没有任何输入道具,它也会被重新渲染。有人能解释一下吗?
所以我的第二个问题是:组件接收到新的 props/state 是什么意思?这是否意味着对象值发生了变化(对于基元来说只是新值,对于对象来说是新引用)?
第三件事:假设应用程序中的父级最顶层组件(例如App.js)发生更改(新道具或新状态),这是否意味着默认情况下所有反应组件当前渲染/安装的(即使是没有任何状态的叶子,也没有改变的道具)会重新渲染?
【问题讨论】:
-
纯组件意味着无状态组件。除了渲染之外,它不使用任何生命周期方法,而且当您使用 PureComponent 时,您实际上并没有修改状态。它的工作原理与 javascript 中的 Pure 函数完全一样,它只接受 props 并返回 JSX 元素。纯组件通过浅比较在内部完成 shouldComponentUpdate 方法的工作
-
这是您的第一个问题 --> shouldComponent - 默认情况下,通过在内部返回 true 来调用此方法,因此无论 prop 或 state 是否更改,此方法都会被调用。在您的情况下,它会像内部一样被调用
标签: reactjs