javascript - ReactJS - 无限循环,setState onChange 方法

标签 javascript reactjs codemirror

我正在使用 codemirror 创建一个组件,但似乎我的代码中有些地方是错误的,因为当我尝试更新我的主要组件的状态时,应用程序破坏了浏览器,我的研究指向一个无限循环,至少我可以在我尝试调试时看到这一点。

希望有人能帮我解决这个问题,也许是我的错,谢谢。

我的主要组成部分:

import React, { Component, PropTypes } from 'react';
import Editor from '../editor';
import Preview from '../preview';

class Playground extends Component {

  constructor(props) {
    super(props);
    this.state = {
      code: 'Hi I am a component',
      newCode: ''
    };
    this.handleCodeChange = this.handleCodeChange.bind(this);
  }

  handleCodeChange(code) {
  // Everything works fine until this step, when the component wants to update the state, start the infinite loop
    this.setState({ newCode: code });
  }

  loadCode(code) {
    this.refs.editor.setCode(code);
  }

  render() {
    return (
      <div>
        <Editor
          ref='editor'
          codeText={this.state.code}
          onChange={this.handleCodeChange}
        />
        <Preview code={this.state.newCode} />
      </div>
    );
  }
}

Playground.propTypes = {
  component: PropTypes.string
};

export default Playground;

我的编辑器组件:

import React, { Component, PropTypes } from 'react';
import style from './style';
import CodeMirror from 'codemirror';
import 'codemirror/mode/javascript/javascript';

class Editor extends Component {
  constructor(props) {
    super(props);
    this.handleChange = this.handleChange.bind(this);
  }

  componentDidMount() {
    this.editor = CodeMirror.fromTextArea(this.refs.editor, {
      lineNumbers: this.props.lineNumbers,
      matchBrackets: true,
      mode: 'javascript',
      readOnly: this.props.readOnly,
      smartIndent: false,
      tabSize: this.props.tabSize,
      theme: this.props.theme
    });

    this.editor.on('change', this.handleChange);
  }

  componentDidUpdate() {
    if ( !this.props.readOnly ) {
      this.editor.setValue(this.props.codeText);
    }
  }

  handleChange() {
    if ( !this.props.readOnly && this.props.onChange ) {
      this.props.onChange(this.editor.getValue());
    }
  }

  render() {
    let _className = style.editor;
    return (
      <div className={ _className }>
        <textarea ref="editor" defaultValue={this.props.codeText} />
      </div>
    );
  }
}

Editor.propTypes = {
  className: React.PropTypes.string,
  codeText: PropTypes.string,
  lineNumbers: PropTypes.bool,
  onChange: PropTypes.func,
  readOnly: PropTypes.bool,
  tabSize: PropTypes.number,
  theme: PropTypes.string
};

Editor.defaultProps = {
  className: '',
  lineNumbers: false,
  readOnly: false,
  tabSize: 2,
  theme: 'one-dark'
};

export default Editor;

我的预览组件

import React, { Component, PropTypes } from 'react';

class Preview extends Component {
  constructor(props) {
    super(props);
  }
  render() {
    return (
      <div>{this.props.code}</div>
    );
  }
}

Preview.propTypes = {
  code: PropTypes.string
};

export default Preview;

如果您需要更多信息或其他信息,请告诉我。

提前致谢。

解决方案

我从编辑器组件中删除了这段代码

componentDidUpdate() {
  if ( !this.props.readOnly ) {
    this.editor.setValue(this.props.codeText);
  }
}

原因是因为此方法为编辑器设置了一个新值,即更新,然后该过程无限地重新开始,如果您手动加载编辑器的内容,则可以使用此方法,但我不是这种情况。

谢谢安东尼

最佳答案

存在无限循环,因为当 CodeMirror 实例发生变化时,您在编辑器组件中调用了 this.handleChange。当您此时调用 this.handleChange 时,您更新了主要组件的状态。

然后,当您更新主组件状态时,它会调用编辑器组件的 componentDidUpdate 函数。您设置 CodeMirror 实例的值,它会触发 change 事件,更新主要组件状态,等等。

为避免此行为,只需比较 componentDidUpdatehandleChange 中的 codeText 以仅在必要时更新。

关于javascript - ReactJS - 无限循环,setState onChange 方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39120394/

相关文章:

reactjs - 更改 MUI 中的 Appbar 背景颜色

reactjs - 错误 TS2430 : Interface 'RcFile' incorrectly extends interface 'File' in antd

javascript - 以 HTML 格式直接输出 PHP 代码

javascript - 仅一行文本字段的代码镜像?

javascript - 在 Javascript 中将函数应用于 Null

javascript - 是否可以为 $httpBackend 响应设置通配符?

html - 将年份值限制为只有 4 位数字

动态缩放容器中的 Javascript 代码编辑器

javascript - 如何使用由多行组成的 django 模板变量分配 javascript 变量?

php - 将数字索引的 PHP 数组传递给 javascript