0

I had a weird problem with componentDidMount and componentWillUnmount behavior. When the component unmount, and then remount again because of the effect of a HOC which come from a library called react-stockchart

Something like this: fitWidth(MyComponent). The behavior of unmount and remount again, whenever the width change is expected.

componentDidMount() {
        this._isMounted = true;
        document.addEventListener("keyup", this.onKeyPress);
        document.addEventListener("touchstart", this.onTouchStart);
        document.addEventListener("touchmove", this.onTouchMove);
        document.addEventListener("touchend", this.onTouchEnd);
        document.addEventListener("touchcancel", this.onTouchEnd);
        window.addEventListener('resize', this.onResize)
        console.log('Remount the MainChart');
    }
componentWillUnmount() {
        this._isMounted = false;
        document.removeEventListener("keyup", this.onKeyPress);
        document.removeEventListener("touchstart", this.onTouchStart);
        document.removeEventListener("touchmove", this.onTouchMove);
        document.removeEventListener("touchend", this.onTouchEnd);
        document.removeEventListener("touchcancel", this.onTouchEnd);
        console.log('Unmounted the MainChart')
    }

I tried to console.log from componentDidMount and componentWillUnmount and see that Unmounted the MainChart --> Remount the MainChart log. But the problem is when I called a function inside this component that have setState statement from another component(using ref), it state that

Can't call setState (or forceUpdate) on an unmounted component. This is a no-op, but it indicates a memory leak in your application. To fix, cancel all subscriptions and asynchronous tasks in the componentWillUnmount method.

The code for that function inside class:

class MainChart extends React.Component {
      constructor(props) {
        super(props);
        
        this.xAxisZoom = this.xAxisZoom.bind(this);
       }
        xAxisZoom(newDomain, callback)
        {
            // Copy from ChartCanvas.js
            const { xScale, plotData, chartConfig } = this.canvas.calculateStateForDomain(newDomain);
            this.canvas.clearThreeCanvas();
            console.log(this._isMounted) //Always false after Remount the MainChart log.
            if (this._isMounted) {
                this.canvas.setState({
                    xScale,
                    plotData,
                    chartConfig,
                }, callback);
            }
        }
    }
 export default fitWidth(MainChart);

The call like this: this.mainchartRef.xAxisZoom(args)

One more note: this.canvas is a ref:

return (

    <ChartCanvas ref={node => {if(node) this.canvas=node;}} width={width} 
        height={mainChartHeight} minPointsPerPxThreshold={0.02}
        mouseMoveEvent={!simpleMode}
    />

Really confused even when the log from componentDidMount has been written, but after execute the function xAxisZoom, it state the component still was unmounted. Why the component seems not yet mounted?

One finding that I have made: When I called the xAxisZoom inside MainChart component itself, it's ok, but calling using ref from another component, it still not yet update the new state of MainChart component. Is there any way to refresh the ref?

NOTE: All the snippets above are in MainChart component . Any idea would be very appreciated.

Minh Kha
  • 1,052
  • 8
  • 13
  • why are you using javascript in react...use react methods – akhtarvahid Sep 25 '20 at 07:02
  • Sorry, I have edited the code, I actually bind that function, the function work normally, the problem was that why it still unmounted? Do u have any idea about that ? – Minh Kha Sep 25 '20 at 07:05
  • Where component are the `componentDidMount` and `componentWillUnmount` in that is getting remounted? Can you provide the component code for `ChartCanvas` so we may see what is being done via the ref? The snippets are very disjointed. Is the third snippet part of `MainChart` component? – Drew Reese Sep 25 '20 at 07:47
  • The `ChartCanvas` is the component from library. `componentDidMount` and `componentWillUnmount`, `xAxisZoom` are inside `MainChart` component. Please notice that I called `xAxisZoom` from another component using ref. – Minh Kha Sep 25 '20 at 07:50
  • Something like: `this.mainChartRef.xAxisZoom(args1, args2)` from another component, not insdie the MainChart itself – Minh Kha Sep 25 '20 at 07:51
  • Those code above are inside `MainChart` component @DrewReese – Minh Kha Sep 25 '20 at 08:05

1 Answers1

0

I found the reason for that, after MainChart component unmount and remount again, the another component which I called AnotherComponent which was holding the MainChart's ref (the old ref of MainChart, hence need to update the new ref).

So what I did here to resolve this issue is passing down a function from AnotherComponent to MainChart for the sake of update ref of MainChart:

class AnotherComponent extends React.Component {
   refreshMainChartRef = (ref) => {
      this.mainChartRef = ref
   }
   return (
     <MainChart refreshMainChartRef={refreshMainChartRef} />
   )
}

class MainChart extends React.Component {
   componentDidMount() {
        this._isMounted = true;
        // That line for update the ref for using from parent
        this.props.refreshMainChartRef(this); 
        document.addEventListener("keyup", this.onKeyPress);
        document.addEventListener("touchstart", this.onTouchStart);
        document.addEventListener("touchmove", this.onTouchMove);
        document.addEventListener("touchend", this.onTouchEnd);
        document.addEventListener("touchcancel", this.onTouchEnd);
        window.addEventListener('resize', this.onResize)
        console.log('Remount the MainChart');
    }
       return (
         ...
       )
 } 
Minh Kha
  • 1,052
  • 8
  • 13