我学到的关于React的一件事是,如果组件的道具没有改变,那么React不会重新渲染组件。这对于无状态组件也是如此吗?或者他们表现得更像“愚蠢”的功能并且每次都被执行?
例如,如果我有:
import StatelessComponent from '../StatelessComponent';
export default class DocumentsTable extends React.Component {
state = {
something: 'foobar',
};
render() {
return (
<div>
{ this.state.something }
<StatelessComponent theOnlyProp='baz'>
</div>
)
}
};
当this.state.something
更新其值时,<StatelessComponent>
会重新呈现吗?或者它是否“聪明”足以看到它的道具没有像其他React组件那样改变?
答案 0 :(得分:51)
自React 16.6起,您可以使用React.memo来阻止重新渲染功能组件,类似于PureComponent
类组件:
const MyComponent = React.memo((props) => {
return (
/* markup */
);
});
另外,备忘录会internal optimization。
与userland memo()高阶组件实现不同,React中内置的实现可以通过避免额外的组件层来提高效率。 块引用
是的,他们总是重新渲染 1 (除非您按照上面的说明使用React.memo)如果在组件本身中调用setState()
或者它的父母,因为功能无状态的组件不带shouldComponentUpdate。实际上,除非实现shouldComponentUpdate
,否则每个React组件都将被重新呈现 1 。
需要注意的是,调用 render()
并不代表DOM节点以任何方式被操纵。 render
方法只是为diff algorithm提供服务来决定哪些DOM节点需要真正附加/分离。 请注意 render()
并不昂贵,而且昂贵的DOM操作。仅当render()
返回不同的虚拟树时才会执行它们。
来自React的documentation
为了清楚起见,在此上下文中重新注册意味着为所有组件调用render,这并不意味着React将卸载并重新安装它们。它只会按照前面章节中规定的规则应用差异。
除非你的组件很庞大,否则不要担心并让render()
被调用,那么你最好使用实现shouldComponentUpdate()
的有状态组件。
看here进行有趣的讨论。
1 表示调用组件的render()
函数,而不是操作底层DOM节点。
答案 1 :(得分:1)
请参阅反应不仅仅是重新渲染如果道具被更改,如果有任何状态变化,它甚至会重新渲染。在您的情况下,组件将在您的状态发生变化时重新渲染。 react的工作方式基于名为 Reconciliation 的算法,该算法的作用是将虚拟DOM与真实DOM进行比较,如果发现任何变化,则通过将其替换为您的实际DOM来重新渲染虚拟DOM因此状态的任何改变都将导致整个组件的重新渲染。
答案 2 :(得分:1)
如果无状态组件的道具未更改,是否会重新渲染?
是的。即使没有任何更改,也会调用无状态渲染功能。但是,React将在对帐阶段将虚拟DOM(由渲染函数生成)与现有DOM进行比较。这还远远不够,因此如果渲染函数的计算成本很高,则不是理想的选择。
纯组件确实具有该属性的默认浅表比较,因此将停止执行渲染。将纯组件视为普通的类React组件,该组件具有 shouldComponentUpdate ,与现有属性和新属性的三元组进行比较。 / p>
话虽如此,您可以使用Recompose.pure(https://github.com/acdlite/recompose/blob/master/docs/API.md#pure)将无状态组件包装为纯组件,就像纯组件,不影响无状态组件的简短语法的浅浅比较。
import StatelessComponent from '../StatelessComponent';
const PureChildFromStatelessComponent = Recompose.pure(StatelessComponent);
// ...
<PureChildFromStatelessComponent ... />