我的纯组件中包含以下代码:
componentDidUpdate(prevProps) {
const { scheduleSheet } = this.props;
const { scheduleSheet: prevScheduleSheet } = prevProps;
if (scheduleSheet !== prevScheduleSheet) {
this.setState({ board: scheduleSheet });
}
}
由于数组是JS中的对象,因此scheduleSheet !== prevScheduleSheet
将始终为true
。那么为什么组件不会陷入无限的更新循环中呢?我的意思是,每次'componentDidUpdate'运行时,都会看到prevProps不等于新的,因此它将更新状态,该状态将运行componentDidUpdate
...那为什么不发生呢?>
this.props.scheduleSheet
的示例(指父组件的状态):
[
null,
null,
[
null,
null,
null,
null,
null,
null,
null,
null,
null,
null,
null,
null,
true
],
[
null,
null,
null,
null,
null,
null,
null,
null,
null,
null,
null,
null,
null,
null,
null,
null,
true
],
[
null,
null,
null,
null,
null,
null,
null,
null,
null,
null,
null,
true
],
[
null,
null,
null,
null,
null,
null,
null,
null,
null,
null,
null,
null,
null,
null,
true
]
]
答案 0 :(得分:0)
您如何通过props
?
const DEFAULT_SHEET = [];
export default class App extends React.Component {
render() {
return <Component scheduleSheet={DEFAULT_SHEET} />
}
}
class Component extends React.Component {
componentDidUpdate(prevProps) {
const { scheduleSheet } = this.props;
const { scheduleSheet: prevScheduleSheet } = prevProps;
// Always false because the reference (props) never change.
if (scheduleSheet !== prevScheduleSheet) {
this.setState({ board: scheduleSheet });
}
}
}
在上面的示例中,引用没有更改,因此scheduleSheet !== prevScheduleSheet
表达式始终为false
,并且不会由于“逻辑”原因而引起inifite循环。
此外,您使用React.PureComponent
,因此在这种情况下,您将不会获得无限循环:
// v NOT PURE COMPONENT, causes infinite loop and crash
class Component extends React.Component {
componentDidUpdate(prevProps) {
const { scheduleSheet } = this.props;
const { scheduleSheet: prevScheduleSheet } = prevProps;
console.log('scheduleSheet', scheduleSheet);
console.log('prevScheduleSheet', prevScheduleSheet);
this.setState({ board: prevScheduleSheet });
}
onChange = e => this.setState({ board: e.target.value });
render() {
return (
<FlexBox>
<Input value={this.state.board} onChange={this.onChange} />
</FlexBox>
);
}
}
这是因为PureComponent
实现了shouldComponentUpdate
并具有较浅的属性和状态比较,从而防止了“不必要的渲染”。
答案 1 :(得分:-3)
来自react docs:
您可以在componentDidUpdate()中立即调用setState(),但请注意 必须将其包装在上面示例中所示的条件下,或者 您将导致无限循环。 这还会导致额外的重新渲染,尽管用户看不到它,但是会影响组件的性能。
这意味着:
if (scheduleSheet !== prevScheduleSheet)
setState
中的componentDidMount
引起的渲染)时,道具已经更新,因此prevProps
和this.props
相同,因此这次条件将不成立,并且更新结束。答案 2 :(得分:-3)
编辑:
我猜错了,假设代码中有if (scheduleSheet !== prevScheduleSheet) {
丹尼斯的答案是正确的。
执行此操作
if (scheduleSheet !== prevScheduleSheet) {
this.setState({ board: scheduleSheet });
}
道具在第一个渲染中是不同的,但是在状态更新之后,道具仅指向同一数组,因为只有状态会改变。
您可以从以下示例中清楚地看到这一点。
对象和数组比较浅,有时会与更新混淆,但是当props不变时,数组是相同的,除非您每次使用具有相同值的新数组更新props。
查看此示例:
更新: 您可以在componentDidUpdate中取消对代码的注释,并查看inifite循环以及为什么在道具不变的情况下它不会显示。