React 中的“无法在现有状态转换期间更新”错误

IT技术 javascript reactjs
2021-03-28 03:54:34

我正在尝试做这个 ReactJS 教程的第 15 步:React.js 介绍给那些只知道足够 jQuery 的人

作者建议如下:

overflowAlert: function() {
  if (this.remainingCharacters() < 0) {
    return (
      <div className="alert alert-warning">
        <strong>Oops! Too Long:</strong>
      </div>
    );
  } else {
    return "";
  }
},

render() {
  ...

  { this.overflowAlert() }

  ...
}

我尝试执行以下操作(对我来说看起来不错):

// 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>

  ...
}

我在 Chrome Dev Tools 的控制台中收到以下错误:

无法在现有状态转换期间更新(例如内部render或另一个组件的构造函数)。Render 方法应该是 props 和 state 的纯函数;构造函数的副作用是一种反模式,但可以移至componentWillMount.

这是一个JSbin 演示为什么我的解决方案不起作用,这个错误是什么意思?

5个回答

您的解决方案不起作用,因为它在逻辑上没有意义。您收到的错误可能有点含糊,让我分解一下。第一行指出:

无法在现有状态转换期间更新(例如在渲染或其他组件的构造函数中)。

每当 React 组件的状态更新时,该组件都会重新渲染到 DOM。在这种情况下,会出现错误,因为您试图调用overflowAlertinside render,它调用setState. 这意味着您正在尝试更新渲染中的状态,然后将调用渲染overflowAlert和更新状态并再次调用渲染等,从而导致无限循环。该错误告诉您,由于首先更新状态,因此您正在尝试更新状态,从而导致循环。这就是为什么这是不允许的。

相反,采取另一种方法并记住您要实现的目标。您是否试图在用户输入文本时向他们发出警告?如果是这种情况,请将其设置overflowAlert为输入的事件处理程序。这样,当输入事件发生时状态将被更新,并且组件将被重新渲染。

确保您使用了正确的表达方式。例如,使用:

<View onPress={this.props.navigation.navigate('Page1')} />

<View onPress={ () => this.props.navigation.navigate('Page1')} />

或者

<View onPress={ () => {
    this.props.navigation.navigate('Page1')
}} />

上面最后两个是函数表达式,第一个不是。确保将函数对象传递给函数表达式() => {}

在组件更新后执行渲染方法中与组件相关的任何任务,而不是在这种情况下,仅在调用 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>
);

  }
}
这解决了我的问题,但我不明白为什么。你可以解释吗?
2021-06-12 03:54:34

每次调用组件props作为新的渲染活动。溢出单个渲染时发生警告。

instead of
<Item onPress = { props.navigation.toggleDrawer() } />
try like
<Item onPress = {() =>  props.navigation.toggleDrawer() } />
<Item onPress = {props.navigation.toggleDrawer} />
2021-06-21 03:54:34

您也可以overflowAlert: function()像这样将函数定义为变量,并且不会在渲染中立即调用

overflowAlert = ()=>{//.....//}