0
votes

I meet problem, when i use componentDidMount(), componentDidMount() use to show Tooltip when use function _getContentTooltip() then the problem show the error common.js:444 RangeError: Maximum call stack size exceeded

import ZCommon from 'utils/common';
import React from 'react';
import ReactDOM from 'react-dom';

class TooltipUtil extends React.Component {
  constructor(props) {
        super(props);
        this.state = {
      guidesContent: [],
      zguides: [],
            current: 1,
      hidden: 0
        };
    }
  shouldComponentUpdate(nextProps, nextState) {
    return (
      this.state.current !== nextState.current ||
      this.state.zguides !== nextState.zguides
    );
  }
  _storageData() {
        this.state.guidesContent = [{
                "id":"1",
          "description": "Đây là title của người chat or group",
                "name":"tabmsg.searchicon",
          "title": "abc",
            }, {
                        "id":"2",
                        "name":"tabmsg.creategroup",
                "description": "Bạn click vào đây để tạo nhóm",
                 "title": "Xưu nhân",
            }, {
                        "id":"3",
                        "name":"csc.header.search",
                "description": "Đây là khung để nhập nội dung chat",
                 "title": "abc",

                                            }];
      this.setState({
        guidesContent: this.state.guidesContent.sort(function(a,b){ return a.id > b.id } )
      });
      return this.state.guidesContent;
  }
  _getContentTooltip(){
    // this.serverRequest.abort();
    let current= this.state.current;
    let _guides = this._storageData();
    let ele = document.querySelectorAll(".tooltip");
    for (var i = 0; i < ele.length; i++) {
        var no = ele[i].getAttribute('data-tooltip');
      let Tcontent = Object.keys(_guides).filter(function(key) {
                if(_guides[key].name == no){
          if(_guides[key].id == current){
            return key;
          }
                }
            });
      this.setState({
        zguides: this.state.guidesContent[Tcontent]
      })
    }
  }
  componentDidMount(){
    this._getContentTooltip();
  }
  componentDidUpdate(){
    this.componentDidMount();
  }
  _handlerClickClose() {
      let _guides = this._storageData();
      if(this.state.current <= _guides.length ){
          this.setState({
            current: this.state.current + 1
          });
      }
  }
  render() {
    let guides = null;
    let obj = this.state.zguides;
    let show = this.state.zguides != undefined ? "show" : ' ';
    console.log(this.state.zguides);
      guides = (
        <div className={'guide ' + show } style={{ width:'200px',left:'0'}}>
          <div className="guide-content flx">
              <div href="#" className="fa fa-close" onClick= {this._handlerClickClose.bind(this)}></div>
              <h4>{this.state.zguides['title']}</h4>
              <p>{this.state.zguides['description']}</p>
          </div>
        </div>
      );
    return guides;
    }
  _handlerClickClose() {
      let _guides = this._storageData();
      if(this.state.current <= _guides.length ){
          this.setState({
            current: this.state.current + 1
          });
      }
  }
}
export default TooltipUtil;
2

2 Answers

0
votes

In _getContentTooltip() function you are changing the state.which causes the component to update so componentDidUpdate() function runs ,which also calling again componentDidMount(). that function again calls getContentTooltip().so comment the below line

componentDidUpdate(){ //this.componentDidMount(); }

0
votes

Fist of all you should not force the lifecycle functions to call forcefully. Now the Maximum Stack Size errors occurs because _getContentTooltip is setting state and hence hence will trigger a rerender resulting in componentDidUpdate lifecycle function being called where you again call componentDidMount thus going in an endless loop. You would say that you have checked whether to previous and current state values are equal in shouldComponentUpdate but comparing arrays like this.state.zguides !== nextState.zguides will return true.

See this answer:

How to compare arrays in JavaScript?

If you want to trigger _getContentTooltip periodically, call it in a setInterval function in componentDidMount

class TooltipUtil extends React.Component {
  constructor(props) {
        super(props);
        this.state = {
      guidesContent: [],
      zguides: [],
            current: 1,
      hidden: 0
        };
    }
  shouldComponentUpdate(nextProps, nextState) {
    return (
      this.state.current !== nextState.current ||
      !this.state.zguides.equals(nextState.zguides)
    );
  }
  _storageData() {
        this.state.guidesContent = [{
                "id":"1",
          "description": "Đây là title của người chat or group",
                "name":"tabmsg.searchicon",
          "title": "abc",
            }, {
                        "id":"2",
                        "name":"tabmsg.creategroup",
                "description": "Bạn click vào đây để tạo nhóm",
                 "title": "Xưu nhân",
            }, {
                        "id":"3",
                        "name":"csc.header.search",
                "description": "Đây là khung để nhập nội dung chat",
                 "title": "abc",

                                            }];
      this.setState({
        guidesContent: this.state.guidesContent.sort(function(a,b){ return a.id > b.id } )
      });
      return this.state.guidesContent;
  }
  _getContentTooltip(){
    // this.serverRequest.abort();
    let current= this.state.current;
    let _guides = this._storageData();
    let ele = document.querySelectorAll(".tooltip");
    for (var i = 0; i < ele.length; i++) {
        var no = ele[i].getAttribute('data-tooltip');
      let Tcontent = Object.keys(_guides).filter(function(key) {
                if(_guides[key].name == no){
          if(_guides[key].id == current){
            return key;
          }
                }
            });
      this.setState({
        zguides: this.state.guidesContent[Tcontent]
      })
    }
  }
  componentDidMount(){
    setInterval(() => {
      this._getContentTooltip();
    }, 1000)
  }
  _handlerClickClose() {
      let _guides = this._storageData();
      if(this.state.current <= _guides.length ){
          this.setState({
            current: this.state.current + 1
          });
      }
  }
  render() {
    let guides = null;
    let obj = this.state.zguides;
    let show = this.state.zguides != undefined ? "show" : ' ';
    console.log(this.state.zguides);
      guides = (
        <div className={'guide ' + show } style={{ width:'200px',left:'0'}}>
          <div className="guide-content flx">
              <div href="#" className="fa fa-close" onClick= {this._handlerClickClose.bind(this)}></div>
              <h4>{this.state.zguides['title']}</h4>
              <p>{this.state.zguides['description']}</p>
          </div>
        </div>
      );
    return guides;
    }
  _handlerClickClose() {
      let _guides = this._storageData();
      if(this.state.current <= _guides.length ){
          this.setState({
            current: this.state.current + 1
          });
      }
  }
}
export default TooltipUtil;