javascript - react 子组件更新父组件时出现反模式错误

标签 javascript reactjs ecmascript-6

我收到错误Uncaught RangeError:超出最大调用堆栈大小。如何消除我的子 (Typewriter) 组件中的此递归函数?我相信我收到此错误是因为我在 ComponentWillUpdate() 中不断调用函数?我该如何解决?我认为通过添加 if 条件,应该可以解决这个问题? 请参阅下面的片段。谢谢!

class Parent extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      typing: true,
    };
    this.interval = null;
    this.handleTyping = this.handleTyping.bind(this);
  }

  handleTyping(doneTyping) {
    if (doneTyping) {
      this.setState({ typing: !this.state.typing });
    }
  }

  render() {
    return (
      <div>
        <h3>{this.state.typing ? "TRUE" : "FALSE"}</h3>
        <Typewriter text={"typewriter_testing"} typeSpeed={50} handleTyping={this.handleTyping}/>
      </div>
    );
  }
}

class Typewriter extends React.Component {
  constructor() {
    super();
    this.state = {
      finalText: '',
      doneTyping: false,
    }
    this.typeWriter = this.typeWriter.bind(this);
  }

  typeWriter(text, n) {
    if (n < (text.length)) {
      if (n + 1 == (text.length)) {
        let j = text.substring(0, n+1);
        this.setState({ finalText: j, doneTyping: !this.state.doneTyping });
        n++;
      }
      else {
        let k = text.substring(0, n+1) + '|';
        this.setState({ finalText: k });
        n++;
      }
      setTimeout( () => { this.typeWriter(text, n) }, this.props.typeSpeed );
    }
  }

  componentDidMount() {
    this.typeWriter(this.props.text, 0);
  }

  componentWillUpdate(nextProps, nextState) {
    if (nextState.doneTyping) {
      nextProps.handleTyping(nextState.doneTyping);
    }
  }

  render() {
    return (
      <div>
        { this.state.finalText }
      </div>
    );
  }
}

ReactDOM.render(<Parent />, app);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

<div id="app"></div>

最佳答案

仅当 doneTyping 发生更改时,此组件才需要在准确时间运行 nextProps.handleTyping(nextState.doneTyping);。 在 componentWillUpdate 中添加另一个条件并检查它:

componentWillUpdate(nextProps, nextState) {
    if (nextState.doneTyping && (nextState.doneTyping !== this.state.doneTyping)) {
      nextProps.handleTyping(nextState.doneTyping);
    }
  }

代码:

class Parent extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      typing: true,
    };
    this.interval = null;
    this.handleTyping = this.handleTyping.bind(this);
  }

  handleTyping(doneTyping) {
    if (doneTyping) {
      this.setState({ typing: !this.state.typing });
    }
  }

  render() {
    return (
      <div>
        <h3>{this.state.typing ? "TRUE" : "FALSE"}</h3>
        <Typewriter text={"typewriter_testing"} typeSpeed={50} handleTyping={this.handleTyping}/>
      </div>
    );
  }
}

class Typewriter extends React.Component {
  constructor() {
    super();
    this.state = {
      finalText: '',
      doneTyping: false,
    }
    this.typeWriter = this.typeWriter.bind(this);
  }

  typeWriter(text, n) {
    if (n < (text.length)) {
      if (n + 1 == (text.length)) {
        let j = text.substring(0, n+1);
        this.setState({ finalText: j, doneTyping: !this.state.doneTyping });
        n++;
      }
      else {
        let k = text.substring(0, n+1) + '|';
        this.setState({ finalText: k });
        n++;
      }
      setTimeout( () => { this.typeWriter(text, n) }, this.props.typeSpeed );
    }
  }

  componentDidMount() {
    this.typeWriter(this.props.text, 0);
  }

  componentWillUpdate(nextProps, nextState) {
    if (nextState.doneTyping && (nextState.doneTyping !== this.state.doneTyping)) {
      nextProps.handleTyping(nextState.doneTyping);
    }
  }

  render() {
    return (
      <div>
        { this.state.finalText }
      </div>
    );
  }
}

ReactDOM.render(<Parent />, app);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

<div id="app"></div>

关于javascript - react 子组件更新父组件时出现反模式错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47321004/

相关文章:

webpack - 如何在 ES6 中导入 SimpleMDE

javascript - 围绕其自身的 y 轴旋转 Collada 模型

javascript - 图像未显示在从 HTML 创建的 PDF 上

reactjs - React 复选框未在功能组件中更新

javascript - Gatsby Context API 不呈现其值

javascript - Node JS 类实例化预期行为

javascript - 无论如何(内置/自定义写入)在 Kendo UI Grid 中进行内联编辑之前显示确认对话框?

javascript - 单独的 js 文件中的 getElementById 找不到 ASP.net 控件

javascript - 在react-native中在headerRight上添加多个按钮

javascript - 奇怪的函数参数