Skip to content

How to change env variables on the fly on a React application

Why change env variables on the fly?

When working in React projects we have the ability to define and use environment variables putting them in an .env file, to use them in our code we just need to use process.env.REACT_APP_VARIABLE, the problem comes when we build the project, so we can deploy it, when building, React will change all the places where we use process.env.REACT_VARIABLE for the actual value of the variable, once the application is built we cannot change this values, so what happens if you want to have dynamic environment variables and change them on the fly, well you will need to change the variables, build again the project and redeploy. We will change this by defining our variables in a config.json file

Creating new React project

First we need to create a new React project

npx create-react-app env-variables
cd env-variables
npm start

Creating config.json file

Now we are going to create a new file called config.json inside the public folder (./public/config.json), when changing this file or adding new variables remember to validate the JSON syntax. By adding this file to public, once we build and deploy the project this file will be available in http://appurl.com/config.json

{
  "REACT_APP_NAME": "Env variables"
}

Creating config class

Next we are going to create a class with some static properties and make them available through all the application, create a new file called config.js inside of src folder

// ./src/config.js

// Class containing all environment variables
export class Config {
    // Static properties shared by all instances with default value for environment variable
    static REACT_APP_NAME = "Default value";

    // Static properties shared by all instances with default value for environment variable
    static REACT_APP_AGE = 10;
}

Fetching values

Now we are going to fetch the values on our json file and change the values of the Config class

// ./src/index.js

import React from 'react';
import ReactDOM from 'react-dom/client';
import './index.css';
import App from './App';
import reportWebVitals from './reportWebVitals';
import { Config } from "./config";


/**
 *
 * @desc Fetch config.json file and changes Config static properties to the values on the file
 */
const fetchConfig = async () => {
    try {
        // Fetch config.json
        const configFile = await fetch("/config.json");
        // Get values as JSON
        const coinfigFileValues = await configFile.json();

        // Change Config class static values to the values on the file
        Object.keys(coinfigFileValues).forEach((key) => {
            Config[key] = coinfigFileValues[key];
        });
    } catch (e) {
        console.log(e);
    }
};

// Load app after we have fetch the values, this way we avoid race conditions, and we make sure we get the values from the file
fetchConfig().then(() => {
    const root = ReactDOM.createRoot(document.getElementById('root'));
    root.render(
        <React.StrictMode>
            <App />
        </React.StrictMode>
    );

    // If you want to start measuring performance in your app, pass a function
    // to log results (for example: reportWebVitals(console.log))
    // or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals
    reportWebVitals();
});

Use variables

To use our environment variables we just need to import { Config } from "./config"; and use the value we need for example Config.REACT_APP_NAME, lets add this values to our App component

// ./src/App.js

import logo from './logo.svg';
import './App.css';
import { Config } from "./config";

function App() {

    /**
     *
     * @desc log environment variable
     */
    const logEnvironmentVariable = () => {
        console.log(Config.REACT_APP_AGE)
    };

    return (
        <div className="App">
            <header className="App-header">
                <img src={logo} className="App-logo" alt="logo" />
                <p>
                    Edit <code>src/App.js</code> and save to reload.
                </p>
                <p>
                    {Config.REACT_APP_NAME}
                </p>
                <p>
                    {Config.REACT_APP_AGE}
                </p>
                <button onClick={() => logEnvironmentVariable()}>Test</button>
                <a
                    className="App-link"
                    href="https://reactjs.org"
                    target="_blank"
                    rel="noopener noreferrer"
                >
                    Learn React
                </a>
            </header>
        </div>
    );
}

export default App;

Change values on the fly

Now you can change your config.json file and reload the page, the app will load the latest values, you don't need to rebuild or redeploy your app. You can access the server or service where you deploy your app and change your config.json, or you could even save your config.json file in another server or service and access this file changing the url where we do the fetch request

Multiple environments

With the current approach we can handle two environments, local which is the default values for the static properties on the Config class and another environment which are the actual values on the config.json file. To handle multiple environments we have multiple solutions and everything depends on how you deploy your app, in my case I use GitHub actions to generate this file for me depending on the environment, you could change the url where we fetch the config.json file to change depending on the environment and have multiple json files for example config-dev.json config-stg.json, or you could add a script to change you json file after the npm run build command

Important

Don't add sensitive data to the environment variables it does not matter which approach you use this one or using the .env files, the values of your variables are visible to everyone and exposing sensitive information like credentials can lead to security risks, if you need to access restricted services or manipulate sensitive data do it on the server or back end instead

GitHub repository

In this repository https://github.com/obravocedillo/EnvVariablesJSON you can find the code.