【问题标题】:"Cannot update during an existing state transition" error in ReactReact 中的“无法在现有状态转换期间更新”错误
【发布时间】:2017-03-12 08:07:11
【问题描述】:

我正在尝试执行本 ReactJS 教程的第 15 步:React.js Introduction For People Who Know Just Enough jQuery To Get By

作者推荐如下:

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 开发工具的控制台中收到以下错误:

在现有状态转换期间无法更新(例如在render 或其他组件的构造函数中)。渲染方法应该是 props 和 state 的纯函数;构造函数的副作用是 反模式,但可以移动到componentWillMount

这是JSbin demo。为什么我的解决方案不起作用?这个错误是什么意思?

【问题讨论】:

  • 想一想:组件在状态更新时会重新渲染,所以如果你在渲染方法中更新状态,那将是一个无限循环。你想在这里完成什么?每当有人输入文本或其他内容时更新状态。
  • @AndrewLi 清醒的回答。继续并将其作为答案归档,我会将其标记为正确。我想在这里完成什么:嗯,我试图以自己的方式做,而不看解决方案,这就是我想出的。

标签: javascript reactjs


【解决方案1】:

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

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

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

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

【讨论】:

    【解决方案2】:

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

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

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

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

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

    【讨论】:

      【解决方案3】:

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

      【讨论】:

      • 这解决了我的问题,但我不明白为什么。你能解释一下吗?
      【解决方案4】:

      每次调用组件道具作为新的渲染活动。溢出单个渲染时出现警告。

      instead of
      <Item onPress = { props.navigation.toggleDrawer() } />
      try like
      <Item onPress = {() =>  props.navigation.toggleDrawer() } />
      

      【讨论】:

      【解决方案5】:

      你也可以像这样将函数overflowAlert: function()定义为一个变量,它不会在render中立即被调用

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

      【讨论】:

        猜你喜欢
        • 2017-10-16
        • 2019-04-05
        • 1970-01-01
        • 2023-03-13
        • 2016-03-31
        • 1970-01-01
        • 2017-05-31
        • 2017-01-05
        相关资源
        最近更新 更多