Javascript React 中的“无法在现有状态转换期间更新”错误
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/42745176/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
"Cannot update during an existing state transition" error in React
提问by thanks_in_advance
I'm trying to do Step 15 of this ReactJS tutorial: React.js Introduction For People Who Know Just Enough jQuery To Get By
我正在尝试做这个 ReactJS 教程的第 15 步:React.js 介绍给那些只知道足够 jQuery 的人
The author recommends the following:
作者建议如下:
overflowAlert: function() {
if (this.remainingCharacters() < 0) {
return (
<div className="alert alert-warning">
<strong>Oops! Too Long:</strong>
</div>
);
} else {
return "";
}
},
render() {
...
{ this.overflowAlert() }
...
}
I tried doing the following (which looks alright to me):
我尝试执行以下操作(对我来说看起来不错):
// initialized "warnText" inside "getInitialState"
overflowAlert: function() {
if (this.remainingCharacters() < 0) {
this.setState({ warnText: "Oops! Too Long:" });
} else {
this.setState({ warnText: "" });
}
},
render() {
...
{ this.overflowAlert() }
<div>{this.state.warnText}</div>
...
}
And I received the following error in the console in Chrome Dev Tools:
我在 Chrome Dev Tools 的控制台中收到以下错误:
Cannot update during an existing state transition (such as within
renderor another component's constructor). Render methods should be a pure function of props and state; constructor side-effects are an anti-pattern, but can be moved tocomponentWillMount.
无法在现有状态转换期间更新(例如内部
render或另一个组件的构造函数)。Render 方法应该是 props 和 state 的纯函数;构造函数的副作用是一种反模式,但可以移至componentWillMount.
Here's a JSbin demo. Why won't my solution work and what does this error mean?
这是一个JSbin 演示。为什么我的解决方案不起作用,这个错误是什么意思?
回答by Andrew Li
Your solution does not work because it doesn't make sense logically. The error you receive may be a bit vague, so let me break it down. The first line states:
您的解决方案不起作用,因为它在逻辑上没有意义。您收到的错误可能有点含糊,让我分解一下。第一行指出:
Cannot update during an existing state transition (such as within render or another component's constructor).
无法在现有状态转换期间更新(例如在渲染或其他组件的构造函数中)。
Whenever a React Component's state is updated, the component is rerendered to the DOM. In this case, there's an error because you are attempting to call overflowAlertinside render, which calls setState. That means you are attempting to update state in render which will in then call render and overflowAlertand update state and call render again, etc. leading to an infinite loop. The error is telling you that you are trying to update state as a consequence of updating state in the first place, leading to a loop. This is why this is not allowed.
每当 React 组件的状态更新时,组件都会重新渲染到 DOM。在这种情况下,会出现错误,因为您试图调用overflowAlertinside render,它调用setState. 这意味着您正在尝试更新渲染中的状态,然后将调用渲染overflowAlert和更新状态并再次调用渲染等,从而导致无限循环。该错误告诉您,由于首先更新状态,因此您正在尝试更新状态,从而导致循环。这就是为什么这是不允许的。
Instead, take another approach and remember what you're trying to accomplish. Are you attempting to give a warning to the user when they input text? If that's the case, set overflowAlertas an event handler of an input. That way, state will be updated when an input event happens, and the component will be rerendered.
相反,采取另一种方法并记住您要完成的任务。您是否试图在用户输入文本时向他们发出警告?如果是这种情况,请将其设置overflowAlert为输入的事件处理程序。这样,当输入事件发生时状态将被更新,并且组件将被重新渲染。
回答by azwar_akbar
Make sure you are using proper expression. For example, using:
确保您使用正确的表达方式。例如,使用:
<View onPress={this.props.navigation.navigate('Page1')} />
is different with
与
<View onPress={ () => this.props.navigation.navigate('Page1')} />
or
或者
<View onPress={ () => {
this.props.navigation.navigate('Page1')
}} />
The two last above are function expression, the first one is not. Make sure you are passing function object to function expression () => {}
上面最后两个是函数表达式,第一个不是。确保将函数对象传递给函数表达式() => {}
回答by Basheer Kohli
Instead of doing any task related to component in render method do it after the update of component In this case moving from Splash screen to another screen is done only after the componentDidMount method call.
在组件更新后执行渲染方法中与组件相关的任何任务,而不是在这种情况下,仅在 componentDidMount 方法调用之后才能从启动画面移动到另一个屏幕。
import React, { Component } from 'react';
import {
StyleSheet,
Text,
View,
Button,
Image,
} from 'react-native';
let timeoutid;
export default class Splash extends Component {
static navigationOptions = {
navbarHidden: true,
tabBarHidden: true,
};
constructor(props) {
super(props)
this.state = { navigatenow: false };
}
componentDidMount() {
timeoutid=setTimeout(() => {
this.setState({ navigatenow: true });
}, 5000);
}
componentWillUnmount(){
clearTimeout(timeoutid);
}
componentDidUpdate(){
const { navigate,goBack } = this.props.navigation;
if (this.state.navigatenow == true) {
navigate('Main');
}
}
render() {
//instead of writing this code in render write this code in
componenetDidUdpate method
/* const { navigate,goBack } = this.props.navigation;
if (this.state.navigatenow == true) {
navigate('Main');
}*/
return (
<Image style={{
flex: 1, width: null,
height: null,
resizeMode: 'cover'
}} source={require('./login.png')}>
</Image>
);
}
}
回答by daRula
You can also define the function overflowAlert: function()as a variable like so and it will not be called immediately in render
您也可以overflowAlert: function()像这样将函数定义为变量,并且不会在渲染中立即调用
overflowAlert = ()=>{//.....//}

