Why from new component my old component useEffect calls are going

Viewed 37

I am having a home component in which i conditionally show another component and on both the component i have setInterval for repetative api calls but when i move to 2nd component then my 1st component useEffect doesn't stop it continuously make api calls, here is the code

HomePage

import React, { useEffect, useState } from "react";
import '../../App.css';
import DetailsPage from '../DetailPage/index';
import Login from "../Login/index";
import LoginPage from '../Login/index';
import {
    Chart as ChartJS,
    CategoryScale,
    LinearScale,
    PointElement,
    LineElement,
    Title,
    Tooltip,
    Legend,
  } from 'chart.js';
  import { Line } from 'react-chartjs-2';

  ChartJS.register(
    CategoryScale,
    LinearScale,
    PointElement,
    LineElement,
    Title,
    Tooltip,
    Legend
  );
  

function HomePage(props){

    const [homeData, setHomeData] = useState([]);
    const [allTickerData, setAllTickerData] = useState(null);
    const [getAllTickerDataGraph, setGetAllTickerDataGraph] = useState(null);
    const [showDetails, setShowDetails] = useState(false);
    const [individualDetails, setIndividualDetails] = useState(null);
    const [userToken, setUserToken] = useState(false);
    const  [userTokenValue, setUserTokenValue] = useState('');
    const [selectedTime,setSelectedTime] = useState(1);
    const [ticker, selectedTicker] = useState(null);


    const options = {
        responsive: true,
        plugins: {
          legend: {
            position: 'top',
          },
          title: {
            display: true,
            text: '',
          },
        },
      };
    const labels = getAllTickerDataGraph && Object.keys(getAllTickerDataGraph);
    const values = getAllTickerDataGraph && Object.values(getAllTickerDataGraph);
    const data = {
        labels,
        datasets: [
          {
            label: 'PNL',
            data: labels && labels.map((item, index) => values && values[index]),
            borderColor: 'rgba(99, 99, 132, 0.5)',
            backgroundColor: 'rgba(99, 99, 132, 0.5)',
          },
        ]
      }

    useEffect(() => {
        let token = localStorage.getItem('userToken');
        if(token && token.length > 0){
            setUserToken(true);
            setUserTokenValue(token);
        }
        if(token != null){
            getData();
            getAllTicker();
            getAllTickerData(selectedTime);
            let intervalId = setInterval(function(){
                getData();
                getAllTickerData(selectedTime);
                getAllTicker();
            }, 20000);
            return(() => {
                clearInterval(intervalId)
            })
        }
        
        
    },[userTokenValue,userToken, selectedTime])

    function getData() {
        var t = `Bearer ${userTokenValue}`
        t = t.replace(/"/g, "")
            const requestOptions = {
                method: 'POST',
            };
            if(t && t.length > 12){
                fetch(`${process.env.REACT_APP_PROXY}/get-all-tickers`, requestOptions).then((data) => {
                    return data.json()
                 }).then((function(data){
                     let arrayData = data && Object.entries(data);
                     setHomeData(arrayData);
                 }))  
            }
    }

    function getAllTicker() {
        var t = `Bearer ${userTokenValue}`
        t = t.replace(/"/g, "")
        const requestOptions = {
            method: 'POST',
        };
        if(t && t.length > 12 ){
            fetch(`${process.env.REACT_APP_PROXY}/get-all`, requestOptions).then((data) => {
                return data.json()
             }).then((function(data){
                 let arrayData = data && Object.entries(data)
                 setAllTickerData(arrayData);
             }))
        }
    }

  function getAllTickerData(days){
    var d = new Date;
    var currentDate = [ d.getFullYear(),
              d.getMonth()+1,
              d.getDate()].join('-')+' '+
              [d.getHours(),
              d.getMinutes(),
              d.getSeconds()].join(':');

    let lastWeek = new Date(d.getFullYear(), d.getMonth(), d.getDate()-days);
    lastWeek = [ lastWeek.getFullYear(),
              lastWeek.getMonth()+1,
              lastWeek.getDate()].join('-')+' '+
              [lastWeek.getHours(),
              lastWeek.getMinutes(),
              lastWeek.getSeconds()].join(':');
    
    let body = {
        ticker: '',
        from_date: lastWeek,
        to_date: currentDate
      }
    var t = `Bearer ${userTokenValue}`
        t = t.replace(/"/g, "")
        const requestOptions = {
            method: 'POST',
            headers: { 'Content-Type': 'application/json', 'Authorization': t },
            body: JSON.stringify(body)
        };
        if(t && t.length > 12 && !showDetails){
            fetch(`${process.env.REACT_APP_PROXY}/get-cumilative_pnl`, requestOptions).then((data) => {
                return data.json()
             }).then((function(data){
                 setGetAllTickerDataGraph(data);
             }))  
        }
  }

  function getTickerData(ticker) {
    selectedTicker(ticker)
    var d = new Date;
    var currentDate = [ d.getFullYear(),
              d.getMonth()+1,
              d.getDate()].join('-')+' '+
              [d.getHours(),
              d.getMinutes(),
              d.getSeconds()].join(':');

    let lastWeek = new Date(d.getFullYear(), d.getMonth(), d.getDate()-1);
    lastWeek = [ lastWeek.getFullYear(),
              lastWeek.getMonth()+1,
              lastWeek.getDate()].join('-')+' '+
              [lastWeek.getHours(),
              lastWeek.getMinutes(),
              lastWeek.getSeconds()].join(':'); 

      
      let body = {
        ticker: `${ticker}`,
        from_date: lastWeek,
        to_date: currentDate
      }
      var t = `Bearer ${userTokenValue}`
        t = t.replace(/"/g, "")
        const requestOptions = {
            method: 'POST',
            headers: { 'Content-Type': 'application/json', 'Authorization': t },
            body: JSON.stringify(body)
        };
        if(t && t.length > 12){
            fetch(`${process.env.REACT_APP_PROXY}/get-data`, requestOptions).then((data) => {
                return data.json()
             }).then((function(data){
                 let arrayData = data && Object.entries(data);
                 console.log(arrayData,"array ka data ")
                 setShowDetails(true);
                 setIndividualDetails(arrayData);
             }))
        }   
    }
    const handleDropdownChange = (e) => {
        setSelectedTime(e.target.value);
        getAllTickerData(e.target.value);
        
    }
    return(
        <div>
            {
                userToken && userToken && userTokenValue.length > 0 && userTokenValue != null? 
                <div>
                        {
                           showDetails && showDetails ? <DetailsPage ticker={ticker} data={individualDetails} allTickerData={allTickerData}/> :
                           <div>
                                <div className="top-div">
                                    <div className="individual-div">PNL: {allTickerData && allTickerData[0] && allTickerData[0][1] && allTickerData[0][1].pnl && Math.round(allTickerData[0][1].pnl)} </div>
                                    <div className="individual-div">POSITION: {allTickerData && allTickerData[0] && allTickerData[0][1] && allTickerData[0][1].position && Math.round(allTickerData[0][1].position)} </div>
                                </div>
                                <div className="low-div">
                                    <div className="left-div">
                                        <table className="table">
                                            <tr>
                                                <th>Ticker</th>
                                                <th>PNL</th>
                                                <th>Position</th>
                                            </tr>
                                        </table>
                                        <table className="table">
                                        {
                                            homeData && Object.keys(homeData).length > 0 ?
                                                homeData.map((data) => {
                                                    return(
                                                    <tr key={data[0]} onClick={() => getTickerData(data[0])}>
                                                        <td>{data[0]}</td>
                                                        <td>{data[1].pnl && data[1].pnl.toFixed(4)}</td>
                                                        <td>{data[1].position && data[1].position.toFixed(4)}</td>
                                                    </tr>
                                                    )
                                                }) : <div>Fetching Data... </div>
                                        }
                                        </table>
                                    </div> 
                                    <div className="right-div">
                                        <Line options={options} data={data} />
                                        <div className="buttons-report-home">
                                            {/* {/* <div onClick={() => getAllTickerData(1)} className="single-button">1 D</div> */}
                                            <select name="days" id="days" onChange={(e) => handleDropdownChange(e)}>
                                                <option value="1">1 D</option>
                                                <option value="7">1 W</option>
                                                <option value="30">1 M</option>
                                                <option value="180">6 M</option>
                                            </select>
                                        </div>
                                    </div>
                                </div>
                           </div>
                          
                        }
                </div> :  <LoginPage />
            }
        </div>
    )

}

export default HomePage;

my another component Details page

import React, { useEffect, useState } from "react";
import '../../App.css';
import {
  Chart as ChartJS,
  CategoryScale,
  LinearScale,
  PointElement,
  LineElement,
  Title,
  Tooltip,
  Legend,
} from 'chart.js';
import { Line } from 'react-chartjs-2';
  
ChartJS.register(
  CategoryScale,
  LinearScale,
  PointElement,
  LineElement,
  Title,
  Tooltip,
  Legend
);


function DetailPage(props){

    const [individualDetails, setIndividualDetails] = useState(props.data);
    const [userToken, setUserToken] = useState(false);
    const  [userTokenValue, setUserTokenValue] = useState(null);
    const [tick, setTick] = useState(props && props.data && props.data[0] && props.data[0]);
    const [all, setAll] = useState(null);
    const [timeSelected, setTimeSelected] = useState(1);

    const options = {
      responsive: true,
      plugins: {
        legend: {
          position: 'top',
        },
        title: {
          display: true,
          text: '',
        },
      },
    };
    const options1 = {
      responsive: true,
      plugins: {
        legend: {
          position: 'top',
        },
        title: {
          display: true,
          text: '',
        },
      },
    };
    const labels = (individualDetails && individualDetails[0] && individualDetails[0][1] && Object.keys(individualDetails[0][1])) || (props && props.data && props.data[0] && props.data[0][1] &&  Object.keys(props.data[0][1]));
    const values = (individualDetails && individualDetails[0] && Object.values(individualDetails[0][1])) || (props && props.data && props.data[0] && props.data[0][1] &&  Object.values(props.data[0][1]));
    const data = {
      labels,
      datasets: [
        {
          label: 'PNL',
          data: labels && labels.map((item, index) => values && values[index] && values[index].pnl),
          borderColor: 'rgba(99, 99, 132, 0.5)',
          backgroundColor: 'rgba(99, 99, 132, 0.5)',
        },
      ],
    };
    const data1 = {
      labels,
      datasets: [
        {
          label: 'POSITION',
          data: labels && labels.map((item, index) => values && values[index] && values[index].position),
          borderColor: 'rgba(255, 99, 132, 0.5)',
          backgroundColor: 'rgba(255, 99, 132, 0.5)',
        }
      ],
    };

    useEffect(() => {
      let token = localStorage.getItem('userToken');
        if(token && token.length > 0){
            setUserToken(true);
            setUserTokenValue(token);
        }
        var tick = props && props.ticker;
        setAll(props.allTickerData);
        setTick(tick);
        let intervalId = 
        setInterval(function(){ 
            getTickerData(tick, timeSelected)
        }, 20000);
        return(() => {
          clearInterval(intervalId)
        })
        
    },[individualDetails, tick,timeSelected])


  function getTickerData(ticker, noOfDays) {
    console.log(ticker, noOfDays,"hey ya ya aya ay")
    var d = new Date;
    var currentDate = [ d.getFullYear(),
              d.getMonth()+1,
              d.getDate()].join('-')+' '+
              [d.getHours(),
              d.getMinutes(),
              d.getSeconds()].join(':');

    let lastWeek = new Date(d.getFullYear(), d.getMonth(), d.getDate() - noOfDays);
    lastWeek = [ lastWeek.getFullYear(),
              lastWeek.getMonth()+1,
              lastWeek.getDate()].join('-')+' '+
              [lastWeek.getHours(),
              lastWeek.getMinutes(),
              lastWeek.getSeconds()].join(':'); 

    let body = {
      ticker: `${ticker}`,
      from_date: lastWeek,
      to_date: currentDate
    }
    var t = `Bearer ${userTokenValue}`
        t = t.replace(/"/g, "")
      const requestOptions = {
          method: 'POST',
          headers: { 'Content-Type': 'application/json', 'Authorization': t },
          body: JSON.stringify(body)
      };
      if(t && t.length > 12){
        fetch(`${process.env.REACT_APP_PROXY}/get-data`, requestOptions).then((data) => {
          return data.json()
       }).then((function(data){
           let arrayData = data && Object.entries(data);
           setIndividualDetails(arrayData);
       }))  
      } 
      
  }

  const handleDropdownChange = (e) => {
    getTickerData(props && props.data && props.data[0] && props.data[0][0], e.target.value);
    setTimeSelected(e.target.value);
  }

  const refreshPage = () => {
    window.location.reload();
  }

    return(
        <div className="detail-div">
            <div className="top-section">
              <div className="back-button" onClick={() => refreshPage()}><span className="back-text">Back</span></div>
              <div className="top-div">
                <div className="individual-div">PNL: {all && all[0] &&  all[0][1] && all[0][1].pnl && all[0][1].pnl} </div>
                <div className="individual-div">POSITION: {all && all[0] &&  all[0][1] && all[0][1].position && all[0][1].position} </div>
              </div>
            </div>
           <div className="ticker-name">{tick}</div>
           <div className="graph-parent">
              <div className="graph-div">
                <Line options={options} data={data} />
                <Line options={options1} data={data1} />
              </div>
              <div className="buttons-report">
                <select name="days" id="days" onChange={(e) => handleDropdownChange(e)}>
                  <option value="1">1 D</option>
                  <option value="7">1 W</option>
                  <option value="30">1 M</option>
                  <option value="180">6 M</option>
                </select>
                {/* {/* <div onClick={() => getTickerData(props && props.data && props.data[0] && props.data[0][0], 1)} className="single-button">1 D</div> */}
            </div>
           </div>
           
        </div>
    )

}

export default DetailPage;

i just want when Detials component render i don't want home page setInterval to work, i am pretty new to hooks, thanks in advance.

1 Answers

The HomePage component is still mounted and being rendered when conditionally rendering the DetailPage component, so the interval timer it instantiated is still running and never cleaned up.

A solution is to add showDetails state to the useEffect hook's dependency and clear the interval when showDetails is true, or rather, only start the interval when showDetails is false.

Example:

useEffect(() => {
  const token = localStorage.getItem('userToken');

  if (token?.length) {
    setUserToken(true);
    setUserTokenValue(token);
  }

  const getAllData = () => {
    getData();
    getAllTicker();
    getAllTickerData(selectedTime);
  };

  getAllData();

  if (token !== null && !showDetails) {        
    const intervalId = setInterval(getAllData, 20000);
    return () => {
      clearInterval(intervalId);
    }
  }
}, [userTokenValue, userToken, selectedTime, showDetails]);
Related