0

I want to populate a grid with many different chart components (Chart1.js, Chart2.js, and so on ...) in react (using "react": "^18.2.0"). For these chart components, I reuse multiple components, including the FetchData.js component which fetches the data from my node.js server.

In most cases, it works fine. But especially when I did not ping the server for a while, the server as well as the database is in sleep mode (I’m using ‘heroku’) and needs some time to wake up, the charts are displaying the wrong data. Data is mixed up between the charts and some charts show different data than what the chart description says.

---------------------- EDIT ------------------------------

I think I might have narrowed down the issue to verifyIdToken from firebase Admin SDK in the backend (using node.js v16.17.0 backend with express ^4.17.1 and firebase-admin: 11.2.0). I'm querying many different data series from a postgres database (with knex ^1.0.1). After I do so I need to verify users idToken as I'm sending back either the complete database result or just parts of it, if the user is not authenticated.

router.get('endpoint/:reqData', (req, res) => {
    const idToken = req.headers.authorization || "unauthorized";

    db.select('dt',req.params.reqData).from('my_table').orderBy('dt')
    .then(json => {
      result = json.map(a => ([Date.parse(a['dt']), parseFloat(a[req.params.reqData])]))
      getAuth()
      .verifyIdToken(idToken)
      .then((decodedToken) => {
        res.send({ 
            data: result,
            name: req.params.reqData
        })
      })
      .catch((error) => {
        result = cut_result_to_unauthorised_user(result);
        res.send({ 
            data: result,
            name: req.params.reqData
        })
      });
    })
    .catch(err => res.status(400).json('error getting ' + req.params.reqData + ' from my_table'))
  })

When I skip the getAuth().verifyIdToken(idToken) part, the data is returned as expected.

How do I chain the database query with knex and the verifyIdToken part correctly?

--------------------- EDIT END ---------------------------

Here are my other components:

The grid where I want to display all charts:

import React from "react";
import {
  Grid,
} from "@mui/material/";

import { Chart1 } from "./Chart1";
import { Chart2 } from "./Chart2";
import { Chart3 } from "./Chart3";
import { Chart4 } from "./Chart4";
import { Chart5 } from "./Chart5";
import { Chart6 } from "./Chart6";
import { Chart7 } from "./Chart7";
import { Chart8 } from "./Chart8";
import { Chart9 } from "./Chart9";

export default function ChartsGrid() {
const data = {
    charts: [
      { chart: <Chart1/> },
      { chart: <Chart2/> },
      { chart: <Chart3/> },
      { chart: <Chart4/> },
      { chart: <Chart5/> },
      { chart: <Chart6/> },
      { chart: <Chart7/> },
      { chart: <Chart8/> },
      { chart: <Chart9/> },
    ],
    id: [1]
  };
  return (
    <>    
      <div >
        {data.id.map((elem) => (
          <Grid
            container
            spacing={2}
            direction="row"
            justify="flex-start"
            alignItems="flex-start"
            key={elem}
          >
            {console.log(elem)}
            {data.charts.map((elem2) => (
                <Grid item xs={12} sm={6} md={4} lg={3} xl={3} key={data.charts.indexOf(elem2)}>
                      {console.log("index ",data.charts.indexOf(elem2)," : ", elem2.chart.type.name)}
                      {elem2.chart}
                </Grid>
            ))}
          </Grid>
        ))}
      </div>
    </>
  );
}

One of the charts I show:

import PlainChart from '../PlainChart';
import Description from './Description';
import FetchData from '../FetchData';
import ChartTitel from './ChartTitle';
import ChartView from '../../pages/ChartView';

const chartName = 'My first chart'
const urls = ["myserver/endpoint/data_1_1", "myserver/endpoint/data_1_2"];

export default function Chart1(){

    const data = FetchData({urls})

    return(
        <>
            <ChartView
                charttitle={<ChartTitel/>}
                chart={
                    <PlainChart 
                        chartName = {chartName}
                        data={data}
                    />
                }
                desc={<Description/>}
            />
        </>
    )
}

I use a ChartView.js which is a material UI Card component that displays the chart as well as some descriptions. The chart itself PlainChart.js is also a component I reuse throughout all charts I'm displaying:

import React, {useState, useEffect } from "react";
import Highcharts from "highcharts/highstock";
import HighchartsReact from "highcharts-react-official";
import ChartLoadingScreen from '../ChartLoadingScreen'

export default function PlainChart({data}){
 
  const HighchartsTheme = {
    series: [ ]
  };

  const [isMounted, setMounted] = useState(false)
  const [options, setOptions] = useState(HighchartsTheme)

  
  useEffect(() => {
    setMounted(false);
    if(data){
      options.series = [{ data: data[0]}];
      options.series.push({ data: data[1]});
      setOptions(prevState => ({ ...prevState}));
      setMounted(true);
    }
  }, [data]);

  return (
    <>
      <div>
        {isMounted ?
          <div>
              <HighchartsReact
                highcharts={Highcharts}
                constructorType={"stockChart"}
                options={options}
              />
          </div>
        :
          <ChartLoadingScreen/>
        }
      </div>
    </>

  );
}

And finally the FetchData.js:

import React, {useEffect, useState} from "react";

export default function FetchData({urls}){

  const [data, setData] = useState(null);

  let headers = new Headers();
  headers.append('Content-Type', 'application/json');
  headers.append('Accept', 'application/json');
  headers.append('GET', 'POST', 'OPTIONS');

  useEffect(() => {
      Promise.all(urls.map(u=>fetch(u, { headers: headers }))).then(responses =>
          Promise.all(responses.map(response => response.json()))
      ).then(data => {
          setData(data)
      }
      ).catch(err => {
          console.log(err)
      }
      );
  }, []);


  return data
}

Might also be important:

I show the charts not only in the grid but also throughout multiple places in the app. Also I don't always use the PlainChart.js for the chart itself, some custom charts require a custom Chart.js, but I always use the ChartView.js.

smaica
  • 723
  • 2
  • 11
  • 26

0 Answers0