0
votes

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.

1
why are you using javascript in react...use react methods - akhtarvahid
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
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
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
Something like: this.mainChartRef.xAxisZoom(args1, args2) from another component, not insdie the MainChart itself - Minh Kha

1 Answers

0
votes

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