使用 shouldComponetUpdate 打破状态设置循环?
Using shouldComponetUpdate to break a state-set loop?
我正在开发一个 React 应用程序,偶然发现如果我不使用 shouldComponentUpdate()
来妨碍我的组件不断相互更新的情况。我正在尝试确定这是否是处理此类更改的最佳方式,或者我是否应该尝试重构我的代码,这样我就不必以这种方式停止更新。
我的实际代码中充满了其他一些正在发生的事情,所以我整理了几个虚拟示例。
父组件:
class App extends React.Component {
constructor() {
super();
this.stateChange = this.stateChange.bind(this);
this.state = {
foo: 'bar'
}
}
stateChange(change) {
this.setState({foo: change});
}
render() {
return (
<div>
<p>Hello World</p>
<ChildComponent stateChange={this.stateChange} />
</div>
)
}
}
子组件:
class ChildComponent extends React.Component {
constructor() {
super();
this.renderDecision = this.renderDecision.bind(this);
this.updateStage = this.updateStage.bind(this);
this.state = {
stage: [1],
hello: 'world'
}
}
updateStage(e) {
let theStage = [...this.state.stage];
theStage.push(1);
this.setState({stage: theStage});
}
renderDecision() {
if (this.state.stage.length < 3) {
return (
<p>There are {this.state.stage.length} items. <button onClick={(e) => this.updateStage(e)}>Click here to update.</button></p>
)
} else if (this.state.stage.length === 3) {
this.props.stateChange(this.state.hello); /// updates the parent which updates the child which updates the parent... ad infinitum
return (
<p>Hello {this.state.hello}, there are {theStage} items.</p>
)
}
}
render() {
return (
<div>
(this.renderDecision())
</div>
)
}
}
如您所见,一旦 stage
数组的长度达到 3 并停留在那里,应用程序和子组件就会被锁定在设置状态的循环中。
这可以通过在 ChildComponent
中添加这样的内容来解决——
componentShouldUpdate() {
if (this.state.stage.length === 3) {
return false;
} else return true;
}
但我想知道这是否是最佳做法,或者我是否应该提出其他解决方案。我的子组件有状态,因为它快速连续地循环通过大约 6 个不同的参数,而应用程序的其余部分不必知道发生了什么,所以通过传递 [=14= 来重新呈现整个应用程序没有意义] 一直回到父级。
希望这个问题是有道理的。感谢阅读。
你永远不应该改变渲染状态,检查这个issue。
在渲染之外做出这些状态决策和人口。
你的做法完全不正确。想想 React 如何更新 DOM。只要组件的状态发生变化,就会调用组件的渲染方法。
在您的组件中,只要调用 render 方法,您就会触发更新状态 (renderDecision) 的函数。因此,当调用渲染时,状态会更新,并且由于状态已更新,再次调用渲染。这会强制无限循环。
解决方法
使用适当的生命周期方法或事件(例如 onClick)来更新状态。我是你的情况,你可以在 componentDidMount 或 componentWillMount
中设置状态
我正在开发一个 React 应用程序,偶然发现如果我不使用 shouldComponentUpdate()
来妨碍我的组件不断相互更新的情况。我正在尝试确定这是否是处理此类更改的最佳方式,或者我是否应该尝试重构我的代码,这样我就不必以这种方式停止更新。
我的实际代码中充满了其他一些正在发生的事情,所以我整理了几个虚拟示例。
父组件:
class App extends React.Component {
constructor() {
super();
this.stateChange = this.stateChange.bind(this);
this.state = {
foo: 'bar'
}
}
stateChange(change) {
this.setState({foo: change});
}
render() {
return (
<div>
<p>Hello World</p>
<ChildComponent stateChange={this.stateChange} />
</div>
)
}
}
子组件:
class ChildComponent extends React.Component {
constructor() {
super();
this.renderDecision = this.renderDecision.bind(this);
this.updateStage = this.updateStage.bind(this);
this.state = {
stage: [1],
hello: 'world'
}
}
updateStage(e) {
let theStage = [...this.state.stage];
theStage.push(1);
this.setState({stage: theStage});
}
renderDecision() {
if (this.state.stage.length < 3) {
return (
<p>There are {this.state.stage.length} items. <button onClick={(e) => this.updateStage(e)}>Click here to update.</button></p>
)
} else if (this.state.stage.length === 3) {
this.props.stateChange(this.state.hello); /// updates the parent which updates the child which updates the parent... ad infinitum
return (
<p>Hello {this.state.hello}, there are {theStage} items.</p>
)
}
}
render() {
return (
<div>
(this.renderDecision())
</div>
)
}
}
如您所见,一旦 stage
数组的长度达到 3 并停留在那里,应用程序和子组件就会被锁定在设置状态的循环中。
这可以通过在 ChildComponent
中添加这样的内容来解决——
componentShouldUpdate() {
if (this.state.stage.length === 3) {
return false;
} else return true;
}
但我想知道这是否是最佳做法,或者我是否应该提出其他解决方案。我的子组件有状态,因为它快速连续地循环通过大约 6 个不同的参数,而应用程序的其余部分不必知道发生了什么,所以通过传递 [=14= 来重新呈现整个应用程序没有意义] 一直回到父级。
希望这个问题是有道理的。感谢阅读。
你永远不应该改变渲染状态,检查这个issue。 在渲染之外做出这些状态决策和人口。
你的做法完全不正确。想想 React 如何更新 DOM。只要组件的状态发生变化,就会调用组件的渲染方法。
在您的组件中,只要调用 render 方法,您就会触发更新状态 (renderDecision) 的函数。因此,当调用渲染时,状态会更新,并且由于状态已更新,再次调用渲染。这会强制无限循环。
解决方法
使用适当的生命周期方法或事件(例如 onClick)来更新状态。我是你的情况,你可以在 componentDidMount 或 componentWillMount
中设置状态