skip to Main Content

I need clarification and some help for a task at work. We have a dashboard that has 2 modes, Sandbox and Production. I have a toggle that switches between the modes. Shown here: Sandbox Production

I want to be able to switch views and if possible the APIs I call when I toggle each mode. Please how can I go about this? I would appreciate any help

I created the toggle bottom in the navbar like this:

import { Switch, Text } from @chakra-ui/react

const [mode, setMode] = useState(true);
function switchMode() {
  setMode(!mode)
}

<Text fontSize={15} mr={2}>
  {mode ? "Sandbox" : "Production"}
</Text>

<Switch onChange={switchMode} />

We have 2 APIs, one for each mode. How can I switch between the two APIs when I toggle the modes?

This is my .env file

VITE_BACKEND_SANDBOX_URL = http://localhost:8000

VITE_BACKEND_PRODUCTION_URL = http://localhost:4000

This is how I’m calling the API:

const getAllCustomers = async (rows, page, token) => {
  const config = {
    headers: {
      Authorization: `Bearer ${token}`,
    },
  };
  const response = await axios.get(
    `${import.meta.env.VITE_BACKEND_SANDBOX_URL}/api/v1/customer/paginate-customer?page=${page}&rows=${rows}`,
    config
  );
  return response.data;
};

2

Answers


  1. There are several ways to handle it.

    First and simplest approach is to store the flag whether the current env is sandbox or production in localStorage whenever there’s an update, and before calling any API endpoint, check that value each time, update the base URL accordingly. You’d probably want an API config file that pulls data from environment variables and store them.

    Psuedo-code:

    // when toggling
    localStorage.setItem('apiEnv', mode);
    
    // api config
    const apiConfig = {
      sandbox: process.env.VITE_BACKEND_SANDBOX_URL,
      production: process.env.VITE_BACKEND_PRODUCTION_URL,
    };
    
    // when calling
    const apiEnv = localStorage.getItem('apiEnv');
    const baseUrl = apiConfig[apiEnv];
    // and use baseUrl for all API helpers
    ...
    

    Another approach is, you can create a global context that stores the flag while also keeping it in localStorage. This way, you only need to pull the localStorage data once when the app mounts for the first time and work with the context state going forward.

    Login or Signup to reply.
  2. You can create an environment file like the following

    const ENVS =  {
      LOCAL: "local",
      SANDBOX:"sandbox",
      PROD: "prod",
    }
    
    const Environments = {
      Sandbox: {
        name: "Sandbox",
        env: "sandbox",
        apiHost: "http://156.21.190.78",
        apiBase: "/api/v1",
      },
      Prod: {
        name: "Production",
        env: "prod",
        apiHost: "http://156.23.190.78",
        apiBase: "/api/v1",
      },
    };
    
    const Environment = {
      current: Environments.Prod,
    };
    
    const ENV_MATCHERS = {
      [ENVS.LOCAL]: ["localhost", "127.0.0.1"],
      [ENVS.SANDBOX]: ["sandbox"],
    };
    
    const isEnv = (hostUrl, environment) => {
      const matchers = ENV_MATCHERS[environment];
    
      if (!matchers) {
        throw new Error("Critical: Error initializing environment");
      }
    
      return matchers.find((match) => hostUrl.includes(match)) !== undefined;
    };
    
    const initEnv = (host: string) => {
      if (isEnv(host, ENVS.LOCAL)) {
        // Environment.current = Environments.Local;
        return ENVS.LOCAL;
      }
    
      if (isEnv(host, ENVS.SANDBOX)) {
        Environment.current = Environments.Sandbox;
        return ENVS.SANDBOX;
      }
    
      Environment.current = Environments.Prod;
      return ENVS.PROD;
    };
    
    const reloadEnvironmentConfig = (env = '') =>
      initEnv(env || window.location.host);
    
    reloadEnvironmentConfig();
    
    export { Environment, reloadEnvironmentConfig };
    

    As you can see above, we are exporting the Environment and reloadEnvironmentConfig function, which will be used to reload the environment

    in your screen import both Environment and reloadEnvironmentConfig function

    import React from "react";
    import { Environment, reloadEnvironmentConfig } from "./environment";
    
    function App() {
      const [env, setEnv] = React.useState(Environment.current.name);
      return (
        <>
          <p>Current ENV: {env}</p>
          <button
            onClick={() => {
              // reloads the environment 
              reloadEnvironmentConfig(env === "Sandbox" ? "Production" : "sandbox");
    
              setEnv(Environment.current.name);
            }}
          >
            change env
          </button>
        </>
      );
    }
    
    export default App;
    

    You can even go further and create an Api class, that manages your api request

    import { Environment } from "./environment";
    
    export class Api {
    
      static getUrl() {
    
        const baseUrl = (Environment.current?.apiHost || '') + (Environment.current?.apiBase || '');
    
        return baseUrl;
    
      }
    
      static get(url, config) {
        const _url = Api.getUrl(url)
        return axios.get(_url, config)
      }
    }
    

    Then in your get all customers function you do

    import { Api, } from "./api";
    
    const getAllCustomers = async (rows, page, token) => {
      const config = {
        headers: {
          Authorization: `Bearer ${token}`,
        },
      };
      const response = await Api.get(`/customer/paginate-customer?page=${page}&rows=${rows}`,config);
      return response.data;
    };
    

    DEMO

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