本文共 6463 字,大约阅读时间需要 21 分钟。
本文翻译自:
Does React re-render all components and sub components every time setState
is called? 每当调用setState
React是否会重新渲染所有组件和子组件?
If so, why? 如果是这样,为什么? I thought the idea was that React only rendered as little as needed - when state changed. 我以为这个想法是,当状态改变时,React只渲染所需的内容。
In the following simple example, both classes render again when the text is clicked, despite the fact that the state doesn't change on subsequent clicks, as the onClick handler always sets the state
to the same value: 在下面的简单示例中,尽管状态在以后的单击中不会改变,但两个类在单击文本时都再次呈现,因为onClick处理程序始终将state
设置为相同的值:
this.setState({'test':'me'});
I would've expected that renders would only happen if state
data had changed. 我曾希望只有在state
数据已更改的情况state
才会进行渲染。
Here's the code of the example, , and embedded snippet: 这是示例代码,例如和嵌入式代码段:
var TimeInChild = React.createClass({ render: function() { var t = new Date().getTime(); return (Time in child:{t}
); } }); var Main = React.createClass({ onTest: function() { this.setState({'test':'me'}); }, render: function() { var currentTime = new Date().getTime(); return (); } }); ReactDOM.render( , document.body);Time in main:{currentTime}
Click me to update time
[1]: http://jsfiddle.net/fp2tncmb/2/
参考:
Does React re-render all components and sub components every time setState is called? 每当调用setState时,React是否会重新渲染所有组件和子组件?
By default - yes. 默认情况下-是。
There is a method boolean shouldComponentUpdate(object nextProps, object nextState) , each component has this method and it's responsible to determine "should component update (run render function)?" 有一个方法boolean shouldComponentUpdate(object nextProps,object nextState) ,每个组件都有此方法,它负责确定“组件应该更新(运行渲染功能)吗?”。 every time you change state or pass new props from parent component. 每次更改状态或从父组件传递新的道具时 。
You can write your own implementation of shouldComponentUpdate method for your component, but default implementation always returns true - meaning always re-run render function. 您可以为组件编写自己的shouldComponentUpdate方法实现,但是默认实现始终返回true-意味着始终重新运行渲染函数。
Quote from official docs 引用官方文档
By default, shouldComponentUpdate always returns true to prevent subtle bugs when state is mutated in place, but if you are careful to always treat state as immutable and to read only from props and state in render() then you can override shouldComponentUpdate with an implementation that compares the old props and state to their replacements. 默认情况下,shouldComponentUpdate始终返回true,以防止状态发生适当变化时产生细微的错误,但是如果您始终将状态视为不可变并仅从props和render()中的状态读取状态,则可以使用实现将旧的道具和状态与其替换进行比较。
Next part of your question: 问题的下一部分:
If so, why? 如果是这样,为什么? I thought the idea was that React only rendered as little as needed - when state changed. 我以为这个想法是,当状态改变时,React只渲染所需的内容。
There are two steps of what we may call "render": 我们可以将“渲染”分为两个步骤:
Virtual DOM render: when render method is called it returns a new virtual dom structure of the component. 虚拟DOM渲染:调用render方法时,它将返回组件的新虚拟dom结构。 As I mentioned before, this render method is called always when you call setState() , because shouldComponentUpdate always returns true by default. 如前所述,此渲染方法总是在您调用setState()时调用,因为默认情况下shouldComponentUpdate始终返回true。 So, by default, there is no optimization here in React. 因此,默认情况下,React中没有优化。
Native DOM render: React changes real DOM nodes in your browser only if they were changed in the Virtual DOM and as little as needed - this is that great React's feature which optimizes real DOM mutation and makes React fast. 原生DOM渲染:仅当在虚拟DOM中更改了真实DOM节点时,React才更改浏览器中的真实DOM节点,并且需要的次数很少-这就是React的一项出色功能,它可以优化真实DOM变异并使其快速运行。
No, React doesn't render everything when state changes. 不,状态更改时,React不会呈现所有内容。
Whenever a component is dirty (its state changed), that component and its children are re-rendered. 每当组件变脏(状态更改)时,都会重新渲染该组件及其子代。 This, to some extent, is to re-render as little as possible. 在某种程度上,这是尽可能少地重新渲染。 The only time when render isn't called is when some branch is moved to another root, where theoretically we don't need to re-render anything. 唯一不调用render的时候就是将某个分支移到另一个根,从理论上讲,我们不需要重新渲染任何东西。 In your example, TimeInChild
is a child component of Main
, so it also gets re-rendered when the state of Main
changes. 在您的示例中, TimeInChild
是Main
的子组件,因此当Main
的状态更改时,它也会重新呈现。
React doesn't compare state data. React不比较状态数据。 When setState
is called, it marks the component as dirty (which means it needs to be re-rendered). 调用setState
,它将组件标记为脏(这意味着它需要重新呈现)。 The important thing to note is that although render
method of the component is called, the real DOM is only updated if the output is different from the current DOM tree (aka diffing between the Virtual DOM tree and document's DOM tree). 需要注意的重要一点是,尽管调用了组件的render
方法,但是仅当输出与当前DOM树不同时(也就是在虚拟DOM树和文档的DOM树之间进行区分),才更新实际DOM。 In your example, even though the state
data hasn't changed, the time of last change did, making Virtual DOM different from document's DOM, hence why the HTML is updated. 在您的示例中,即使state
数据没有更改,上次更改的时间也发生了更改,从而使Virtual DOM与文档的DOM有所不同,因此,为什么要更新HTML。
Yes. 是。 It calls the render() method every time we call setState instead when "shouldComponentUpdate" returns false. 每当“ shouldComponentUpdate”返回false时,它将每次调用setState时调用render()方法。
Even though it's stated in many of the other answers here, the component should either: 即使在这里的许多其他答案中都已说明,该组件也应该:
implement shouldComponentUpdate
to render only when state or properties change 实现shouldComponentUpdate
以仅在状态或属性更改时呈现
switch to extending a , which already implements a shouldComponentUpdate
method internally for shallow comparisons. 切换到扩展 ,该方法已经在内部实现了shouldComponentUpdate
方法以进行浅表比较。
Here's an example that uses shouldComponentUpdate
, which works only for this simple use case and demonstration purposes. 这是一个使用shouldComponentUpdate
的示例,该示例仅用于此简单用例和演示目的。 When this is used, the component no longer re-renders itself on each click, and is rendered when first displayed, and after it's been clicked once. 使用此功能后,组件将不再在每次单击时重新呈现其自身,而是在首次显示时以及单击一次后呈现。
var TimeInChild = React.createClass({ render: function() { var t = new Date().getTime(); return (Time in child:{t}
); } }); var Main = React.createClass({ onTest: function() { this.setState({'test':'me'}); }, shouldComponentUpdate: function(nextProps, nextState) { if (this.state == null) return true; if (this.state.test == nextState.test) return false; return true; }, render: function() { var currentTime = new Date().getTime(); return (); } }); ReactDOM.render( , document.body);Time in main:{currentTime}
Click me to update time
转载地址:http://wfexb.baihongyu.com/