0

I'm no expert at React and I'm facing an issue where an HTTP request is being made multiple times and through the React profiler I noticed multiple calls by the BrowserRouter. I have absolutely no idea why I'm getting these double calls.

I'm using Django and here's the HTTP calls:

System check identified no issues (0 silenced).
August 29, 2023 - 10:57:35
Django version 4.2.3, using settings 'REDACTED.settings'
Starting development server at http://127.0.0.1:8000/
Quit the server with CTRL-BREAK.

[29/Aug/2023 10:57:37] "OPTIONS /users/api/v1/token/ HTTP/1.1" 200 0
[29/Aug/2023 10:57:38] "POST /users/api/v1/token/ HTTP/1.1" 200 483
[29/Aug/2023 10:57:38] "OPTIONS /users/api/v1/token/refresh/ HTTP/1.1" 200 0
[29/Aug/2023 10:57:38] "POST /users/api/v1/token/refresh/ HTTP/1.1" 200 483
[29/Aug/2023 10:57:38] "OPTIONS /users/api/v1/token/refresh/ HTTP/1.1" 200 0
[29/Aug/2023 10:57:38] "POST /users/api/v1/token/refresh/ HTTP/1.1" 200 483
[29/Aug/2023 10:57:38] "OPTIONS /dashboards/api/v1/dashboards/ HTTP/1.1" 200 0
[29/Aug/2023 10:57:38] "OPTIONS /dashboards/api/v1/dashboards/ HTTP/1.1" 200 0
[29/Aug/2023 10:57:38] "GET /dashboards/api/v1/dashboards/ HTTP/1.1" 200 146
[29/Aug/2023 10:57:38] "OPTIONS /users/api/v1/token/refresh/ HTTP/1.1" 200 0
[29/Aug/2023 10:57:38] "OPTIONS /users/api/v1/token/refresh/ HTTP/1.1" 200 0
[29/Aug/2023 10:57:38] "POST /users/api/v1/token/refresh/ HTTP/1.1" 200 483
[29/Aug/2023 10:57:38] "POST /users/api/v1/token/refresh/ HTTP/1.1" 200 483
[29/Aug/2023 10:57:38] "OPTIONS /dashboards/api/v1/embed/REDACTED/REDACTED/ HTTP/1.1" 200 0
[29/Aug/2023 10:57:38] "OPTIONS /dashboards/api/v1/embed/REDACTED/REDACTED/ HTTP/1.1" 200 0
[29/Aug/2023 10:57:39] "GET /dashboards/api/v1/dashboards/ HTTP/1.1" 200 146
[29/Aug/2023 10:57:40] "GET /dashboards/api/v1/embed/REDACTED/REDACTED/ HTTP/1.1" 200 2555
[29/Aug/2023 10:57:40] "GET /dashboards/api/v1/embed/REDACTED/REDACTED/ HTTP/1.1" 200 2555

This is my app.tsx

import React from 'react';
import { BrowserRouter as Router, Routes, Route, Navigate } from 'react-router-dom';
import './App.css';
import Login from './Login';
import SelectDashboard from './SelectDashboard';
import ViewDashboard from './ViewDashboard';

const App: React.FC = () => {
  return (
    <Router>
      <Routes>
        <Route path="/login" element={<Login />} />
        <Route path="/" element={<Login />} />
        <Route path="/select-dashboard" element={<SelectDashboard />} />
        <Route path="/dashboard" element={<ViewDashboard />} />
        <Route
          path="*"
          element={<Navigate to="/" replace />}
        />
      </Routes>
    </Router>
  );
};

export default App;

Finally, ViewDashboard.tsx:

import React, { useState, useEffect } from 'react';
import { useNavigate } from 'react-router-dom';
import * as pbi from 'powerbi-client';
import './App.css';

const ViewDashboard: React.FC = () => {
  const navigate = useNavigate();
  const [embedData, setEmbedData] = useState<any | null>(null);

  const handleLogout = () => {
    // Clear localStorage items
    localStorage.removeItem('refresh');
    localStorage.removeItem('selectedWorkspaceId');
    localStorage.removeItem('selectedReportId');

    navigate('/login');
  };

  const getEmbed = async () => {
    // Try to get the refresh token from local storage
    try {
      const refresh = localStorage.getItem('refresh') || '';
      const refreshRequestBody = JSON.stringify({ refresh });

      // Get a new access token
      const newTokenResponse = await fetch('http://localhost:8000/users/api/v1/token/refresh/', {
        method: 'POST',
        headers: {
          'Content-Type': 'application/json'
        },
        body: refreshRequestBody,
      });

      const newToken = await newTokenResponse.json();
      localStorage.setItem('jwt', newToken.access);

      const response = await fetch(
        'http://localhost:8000/dashboards/api/v1/embed/' +
          localStorage.getItem('selectedWorkspaceId') +
          '/' +
          localStorage.getItem('selectedReportId') +
          '/',
        {
          method: 'GET',
          headers: {
            'Content-Type': 'application/json',
            Authorization: 'Bearer ' + localStorage.getItem('jwt'),
          },
        }
      );
      const data = await response.json();
      return data;
    } catch (error) {
      redirect('/login');
    }
  };

  const redirect = (path: string) => {
    navigate(path);
  };

  const embedDashboard = async () => {
    try {
      const data = await getEmbed();
      setEmbedData(data);
    } catch (error) {
      throw error;
    }
  };

  useEffect(() => {
    embedDashboard();
  }, []); // Only run once when the component mounts

  useEffect(() => {
    if (embedData) {
      // Embed the Power BI dashboard here
      const config: pbi.IEmbedConfiguration = {
        type: 'report',
        id: embedData.reports[0].id,
        embedUrl: embedData.reports[0].embedUrl,
        accessToken: embedData.token,
        tokenType: pbi.models.TokenType.Embed,
      };

      const embedContainer = document.querySelector('.report-div');
      if (embedContainer) {
        // @ts-ignore
        const dashboard = powerbi.embed(embedContainer, config);
        dashboard.off('loaded'); // Prevent any additional event listeners
      }
    }
  }, [embedData]);

  return (
    <>
      <div className="horizontal-bar">
        <button onClick={handleLogout} className="logout-button">
          Logout
        </button>
      </div>
      <div className="dashboard-container">
        <div className="report-div"></div>
      </div>
    </>
  );
};

export default ViewDashboard;
Drew Reese
  • 165,259
  • 14
  • 153
  • 181
  • 1
    Are you rendering the app into the `React.StrictMode` component and currently using a non-production build? Does this help answer your question? https://stackoverflow.com/q/72238175/8690857 – Drew Reese Aug 29 '23 at 17:09
  • @DrewReese [This answer](https://stackoverflow.com/a/74609594/19745273) kinda helped. I used that proposed logic and now I only get one call. Thank you! – Ricardo Tejada Aug 29 '23 at 17:26
  • Sure. Keep in mind that "isMounted" logic is now generally considered a React anti-pattern. Better to use the `useEffect` hook correctly and cleanup any outstanding subscriptions/network requests/etc for when the component unmounts. – Drew Reese Aug 29 '23 at 17:36

0 Answers0