Bra*_*rks 445 javascript reactjs
React是否每次都会重新渲染所有组件和子组件setState?
如果是这样,为什么?我认为这个想法是React只在需要的时候渲染 - 当状态改变时.
在下面的简单示例中,两个类在单击文本时再次呈现,尽管状态在后续单击时不会更改,因为onClick处理程序始终将其state设置为相同的值:
this.setState({'test':'me'});
Run Code Online (Sandbox Code Playgroud)
我希望渲染只会在state数据发生变化时发生.
以下是该示例的代码,作为JS Fiddle和嵌入式代码段:
var TimeInChild = React.createClass({
render: function() {
var t = new Date().getTime();
return (
<p>Time in child:{t}</p>
);
}
});
var Main = React.createClass({
onTest: function() {
this.setState({'test':'me'});
},
render: function() {
var currentTime = new Date().getTime();
return (
<div onClick={this.onTest}>
<p>Time in main:{currentTime}</p>
<p>Click me to update time</p>
<TimeInChild/>
</div>
);
}
});
ReactDOM.render(<Main/>, document.body);Run Code Online (Sandbox Code Playgroud)
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.0.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.0.0/react-dom.min.js"></script>Run Code Online (Sandbox Code Playgroud)
[1]: http://jsfiddle.net/fp2tncmb/2/
Run Code Online (Sandbox Code Playgroud)
Pet*_*etr 518
每次调用setState时,React都会重新渲染所有组件和子组件吗?
默认情况下 - 是的.
有一个方法boolean shouldComponentUpdate(object nextProps,object nextState),每个组件都有这个方法,它负责确定"应该组件更新(运行渲染函数)?" 每次更改状态或从父组件传递新的道具时.
您可以为组件编写自己的shouldComponentUpdate方法实现,但默认实现始终返回true - 意味着始终重新运行render函数.
从官方文档引用http://facebook.github.io/react/docs/component-specs.html#updating-shouldcomponentupdate
默认情况下,shouldComponentUpdate始终返回true以防止在状态发生变异时出现细微错误,但是如果您小心始终将状态视为不可变并且只读取render()中的props和state,那么您可以使用以下实现覆盖shouldComponentUpdate将旧的道具和州与他们的替代品进行比较.
问题的下一部分:
如果是这样,为什么?我认为这个想法是React只在需要的时候渲染 - 当状态改变时.
我们称之为"渲染"的步骤分为两步:
虚拟DOM渲染:调用render方法时,它返回组件的新虚拟dom结构.正如我之前提到的,当你调用setState()时,总会调用这个render方法,因为默认情况下shouldComponentUpdate总是返回true.因此,默认情况下,React中没有优化.
原生DOM渲染:只有在虚拟DOM中更改并且根据需要更改时,React才会更改浏览器中的真实DOM节点 - 这就是React的优秀功能,它可以优化真正的DOM突变并使React快速运行.
tun*_*ngd 91
不,当状态发生变化时,React不会渲染所有内容.
每当组件变脏(其状态发生变化)时,该组件及其子组件将被重新呈现.在某种程度上,这是尽可能少地重新渲染.没有调用render的唯一时间是将某个分支移动到另一个根,理论上我们不需要重新渲染任何东西.在您的示例中,TimeInChild是子组件Main,因此在Main更改状态时也会重新呈现.
React不会比较状态数据.当setState被调用时,它标志着成分为脏(这意味着它需要被重新呈现).需要注意的重要一点是,尽管render调用了组件的方法,但只有当输出与当前DOM树(也就是虚拟DOM树和文档的DOM树之间的差异)不同时,才会更新真正的DOM.在您的示例中,即使state数据没有更改,上次更改的时间也会发生,使Virtual DOM与文档的DOM不同,因此HTML更新的原因.
lif*_*foo 11
从 React 18 开始,所有状态更新都会自动批处理。通过这种方式,React 将多个状态更新分组到单个重新渲染中,以获得更好的性能。
因此,当您更新状态时,React 总是尝试在组更新中批处理这些更新,从而导致渲染次数少于调用次数setState。使用 hooks 时的行为是相同的。
您可以在React 18公告的自动批处理中阅读非常长的解释。
在 React 17 及更低版本中,仅对 React 事件处理程序内部的更新进行批处理。默认情况下,React 中不会批量处理由 Promise、setTimeout、本机事件处理程序或其他事件触发的更新。
Bra*_*rks 10
即使在这里的许多其他答案中都有说明,该组件也应该:
实现shouldComponentUpdate仅在状态或属性更改时呈现
切换到扩展PureComponent,它已经在shouldComponentUpdate内部实现了一个用于浅层比较的方法。
这是一个使用 的示例shouldComponentUpdate,它仅适用于这个简单的用例和演示目的。使用此选项时,组件不再在每次单击时重新渲染自身,并在首次显示时和单击一次后进行渲染。
var TimeInChild = React.createClass({
render: function() {
var t = new Date().getTime();
return (
<p>Time in child:{t}</p>
);
}
});
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 (
<div onClick={this.onTest}>
<p>Time in main:{currentTime}</p>
<p>Click me to update time</p>
<TimeInChild/>
</div>
);
}
});
ReactDOM.render(<Main/>, document.body);Run Code Online (Sandbox Code Playgroud)
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.0.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.0.0/react-dom.min.js"></script>Run Code Online (Sandbox Code Playgroud)
“丢失更新”的另一个原因可能是:
如果是问题,那么您可以避免在更新期间设置状态,您应该像这样检查状态参数值
static getDerivedStateFromProps(props: TimeCorrectionProps, state: TimeCorrectionState): TimeCorrectionState {
return state ? state : {disable: false, timeCorrection: props.timeCorrection};
}
Run Code Online (Sandbox Code Playgroud)
另一种解决方案是向状态添加一个初始化属性,并在第一次时设置它(如果状态初始化为非空值)。
当使用 React 钩子时,似乎接受的答案不再是这种情况(使用原始值,请参阅对此答案的评论以获取详细信息)。你可以在这个代码沙箱中看到,当状态设置为相同的值时,类组件会被重新渲染,而在函数组件中,将状态设置为相同的值不会导致重新渲染。
https://codesandbox.io/s/still-wave-wouk2?file=/src/App.js
| 归档时间: |
|
| 查看次数: |
206470 次 |
| 最近记录: |