0

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;
Rob
  • 26,989
  • 16
  • 82
  • 98
Bi Híp
  • 103
  • 1
  • 12

2 Answers2

0

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(); }

yasarui
  • 6,209
  • 8
  • 41
  • 75
0

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;
Shubham Khatri
  • 270,417
  • 55
  • 406
  • 400
  • i used code for you that so show the error and warning `Warning: performUpdateIfNecessary: Unexpected batch number (current 99, pending 6)` and `this.state.zguides.equal is not a function` if i'm comment //this.componentDidMount(); when click close and current update, tooltip not get next content – Bi Híp Jul 21 '17 at 05:50
  • I had provided a link to compare arrays in my answer check that, There was a typo in my code – Shubham Khatri Jul 21 '17 at 06:39