skip to Main Content

I am using axios to get an array from a JSON file and I want to use the same array over multiple nodes / pages.

Currently I’m using this on each page var printers = GetPrinters();

I was trying call GetPrinters() from the App.tsx and pass it to each page via a router but I couldn’t seem to get that to work. Is there a way I can store the array on state and access it on any node?

I plan to make 4 more pages similar to MonoPrints.tsx that all need access to the data from the array, they won’t be updating the array at all, just accessing it.

I would like to use the best practice for this kind of thing and am stuck with repeating the call for each page at the moment.

Site Structure:
App.tsx

import { BrowserRouter, Routes, Route } from "react-router-dom";
import { TonerLevels } from "./pages/TonerLevels";
import { MonoPrints } from "./pages/MonoPrints";
import { MonoCopies } from "./pages/MonoCopies";
import { ColourPrints } from "./pages/ColourPrints";
import { ColourCopies } from "./pages/ColourCopies";

export function App() {
  return (
    <BrowserRouter>
      <Routes>
        <Route path="/TonerLevels" element={<TonerLevels />}></Route>
        <Route path="/MonoPrints" element={<MonoPrints />}></Route>
        <Route path="/MonoCopies" element={<MonoCopies />}></Route>
        <Route path="/ColourPrints" element={<ColourPrints />}></Route>
        <Route path="/ColourCopies" element={<ColourCopies />}></Route>
      </Routes>
    </BrowserRouter>
  );
}

Pages/
TonerLevels

export function TonerLevels() {
  var printers = GetPrinters();
  return (
    <div>
      <Nav></Nav>
      <table className="table table-dark table-hover">
        <thead>
          <tr>
            <th>Location</th>
            <th>IP</th>
            <th>Name</th>
            <th>Serial</th>
            <th>Black %</th>
            <th>Yellow %</th>
            <th>Magenta %</th>
            <th>Cyan %</th>
            <th>K1 %</th>
            <th>K2 %</th>
            <th>Current Monthly Prints</th>
            <th>Current Monthly Copies</th>
          </tr>
        </thead>
        <tbody className="table-group divider">
          {printers
            ? printers.map((printer) => {
                return (
                  <tr key={printer.address}>
                    <td>{printer.location}</td>
                    <td>
                      <a
                        href={"//" + printer.address}
                        target="_blank"
                        rel="noopener noreferrer"
                      >
                        {printer.address}
                      </a>
                    </td>
                    <td>{printer.name}</td>
                    <td>{printer.serial}</td>
                    <td>{printer.black > -1 ? printer.black : ""}</td>
                    <td>{printer.yellow > -1 ? printer.yellow : ""}</td>
                    <td>{printer.magenta > -1 ? printer.magenta : ""}</td>
                    <td>{printer.cyan > -1 ? printer.cyan : ""}</td>
                    <td>{printer.k1 > -1 ? printer.k1 : ""}</td>
                    <td>{printer.k2 > -1 ? printer.k2 : ""}</td>
                    <td>{getPrints(printer)}</td>
                    <td>{getCopies(printer)}</td>
                  </tr>
                );
              })
            : null}
        </tbody>
      </table>
    </div>
  );
}

Services/
PrinterServices

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

const PRINTER_REST_API_URL = "http://localhost:8080/GetReport";

export interface Printer {
  address: string;
  black: number;
  monoCopies: number;
  monoPrints: number;
  colourCopies: number;
  colourPrints: number;
  cyan: number;
  k1: number;
  k2: number;
  location: string;
  magenta: number;
  name: string;
  serial: string;
  yellow: number;
  Reports: [
    {
      month: string;
      monoPrints: number;
      monoCopies: number;
      colourPrints: number;
      colourCopies: number;
    }
  ];
}

export function GetPrinters() {
  const [printers, setPrinters] = useState<Printer[] | null>();
  useEffect(() => {
    axios.get(PRINTER_REST_API_URL).then((response) => {
      setPrinters(response.data);
    });
  }, []);
  return printers;
}

2

Answers


  1. Yes, there are options available to maintain state at higher level and consume it across the components.

    1. Context API – helps passing data deeply into the tree and can be accessible only within the hierarchy. (Official doc: https://react.dev/reference/react/useContext).

    2. React Redux – Manages state at app level and can be accessible from any components. (Official doc: https://redux-toolkit.js.org/introduction/getting-started)

    Option 1 can be used for your case as it looks simpler and manageable.

    Option 2 can be used for large scale application with complex state management.

    Login or Signup to reply.
  2. You can use "React Context" to store the array on a global state and then access it from any component.

    Context code would look like this in Javascript:

    import React, { useState, createContext, useEffect } from "react";
    import axios from "axios";
    
    const Context = createContext();
    
    export const ContextProvider = ({ children }) => {
      const [printers, setPrinters] = useState();
      useEffect(() => {
        axios.get("PRINTER_REST_API_URL").then((response) => {
          setPrinters(response.data);
        });
      }, []);
    
      return (
        <Context.Provider
          value={{
            printers,
          }}
        >
          {children}
        </Context.Provider>
      );
    };
    
    export default Context;
    

    Then add ContextProvider in your app.js

    import { BrowserRouter, Routes, Route } from "react-router-dom";
    import { TonerLevels } from "./pages/TonerLevels";
    import { MonoPrints } from "./pages/MonoPrints";
    import { MonoCopies } from "./pages/MonoCopies";
    import { ColourPrints } from "./pages/ColourPrints";
    import { ColourCopies } from "./pages/ColourCopies";
    
    export function App() {
      return (
        <ContextProvider>
          <BrowserRouter>
            <Routes>
              <Route path="/TonerLevels" element={<TonerLevels />}></Route>
              <Route path="/MonoPrints" element={<MonoPrints />}></Route>
              <Route path="/MonoCopies" element={<MonoCopies />}></Route>
              <Route path="/ColourPrints" element={<ColourPrints />}></Route>
              <Route path="/ColourCopies" element={<ColourCopies />}></Route>
            </Routes>
          </BrowserRouter>
        </ContextProvider>
      );
    }
    

    Now you can simply use useContext hook to access the printers state from any component.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search