在创建mapStateToProps时,创建一个新的axios调用

时间:2018-08-17 22:00:58

标签: reactjs react-redux axios

我创建了一个ReactMap组件,该组件接收mapStateToProps函数调用。除了使用Axios进行ajax调用外,其他所有功能都正常。

mapStateToProps更新上的类需要调用服务器,并将其有效负载添加到组件的状态并更新文本区域。

我从控制台收到的错误是

ReactDOMIDOperations.js:47 Uncaught RangeError: Maximum call stack size exceeded

以下是我到目前为止的内容。谁能告诉我如何解决此问题?

import React from "react";
import { connect } from "react-redux";
import ApiCalls from "../../../utils/ApiCalls";

const mapStateToProps = state => {
  return { passFilePath: state.passFilePath };
};



/**
 *  This component is a template to display
 *  widgets of information
 */
class IdeTextEditorClass extends React.Component {
  constructor() {
    super();
    this.state = {
      newData: [],
      pathData: []
    }
  }


  /**
   *  Received request from server add it to 
   *  react component so that it can be rendered
   */
  componentDidUpdate() {

    try {
      this.setState({ pathData: this.props.passFilePath[this.props.passFilePath.length - 1] });
    } catch (err) {
      this.setState({ pathData: '' });
    }

    console.log('path', this.state.pathData.data);
    ApiCalls.readSassFile(this.state.pathData.data)
      .then(function (serverData) {
       this.setState({ newData: serverData[0].data })
      }.bind(this));
  }


  render() {

    try {
      this.state.newData
    } catch (err) {
      this.setState({ newData: '' });
    }


    return (
      <fieldset>
        <input type="text" value={this.state.pathData.data} />
        <textarea id="ide-text-area" name="ide-text-area" value={this.state.newData} /></fieldset>
    )
  }
}

const IdeTextEditor = connect(mapStateToProps)(IdeTextEditorClass);
export default IdeTextEditor;

1 个答案:

答案 0 :(得分:0)

class IdeTextEditorClass extends React.Component {
  constructor() {
    super();
    /*
    based on your original code it seems the default data should be empty string ,as you set them to be empty string when you cannot get data from server. 
    */
    this.state = {
      newData: '',
      pathData: ''
    }
  }


  /**
   *  Received request from server add it to 
   *  react component so that it can be rendered
   */
  componentDidMount() {
    try {
      this.setState({ pathData: this.props.passFilePath[this.props.passFilePath.length - 1] });
    } catch (err) {
      this.setState({ pathData: '' });
    }

    console.log('path', this.state.pathData.data);
    ApiCalls.readSassFile(this.state.pathData.data)
      .then(function (serverData) {
       this.setState({ newData: serverData[0].data })
      }.bind(this));
  }


  render() {
    //by default your newData is already empty string. so skip the checking here.

    let path = this.state.pathData ? this.state.pathData.data : '';    

    return (
      <fieldset>
        <input type="text" value={path} />
        <textarea id="ide-text-area" name="ide-text-area" value={this.state.newData} /></fieldset>
    )
  }
}

说明: 主要更改是将componentDidUpdate更改为componentDidMount。 将数据初始化逻辑放在componentDidMount中是因为:

  1. 仅调用一次,因此避免了注释中提到的无休止的更新循环。另外,通常在这里需要初始化逻辑。

  2. 此方法在初始渲染之后被调用,因此您至少可以在等待数据期间(从服务器)向用户显示某些内容。例如,在您的render方法中,您可以检查newData,如果不可用,则显示一个加载图标。然后React调用componentDidMount,并获取数据->更新状态->再次触发渲染->使用从服务器获取的新数据显示输入/文本区域。当然,如果您不想打扰显示加载图标,那也很好,因为当ajax调用返回时,您的视图可能会快速更新。