6

Using React Hooks To Save the Environment

 3 years ago
source link: https://keyholesoftware.com/2021/04/08/using-environment-variables-with-react-hooks/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
Using React Hooks To Save the Environment

Every application has some need for environmental variables that are specific to that environment. This can be database connections strings or URL to an API that will vary between the different environments. In React, you can use .env files to define key-value pairs. Then Node will inject these at runtime to be used globally through the process.env.{variable}.

In this blog, we will go through the process of creating a React project with environment variables and a custom hook to use those environment variables. Finally, we’ll cover how to configure the project to use multiple environments. Let’s get started!

Note: if you’re new to React Hooks, make sure to check out this introductory React Hooks blog with code examples.

Project Setup

First, let’s create a new React project with TypeScript. I’m using VScode and Yarn to run the create React app template from the terminal.

 
yarn create react-app example-app --template typescript 
cd example-app
yarn start 

Next, create a new folder under src called components. In the folder, create a new file called Example.tsx. Then, in the file, add the following.

import React, { useState } from "react";
const Example: React.FC = () => {
  return (
    <div>
      <h1>An Okay Title</h1>
    </div>
  );
};
export default Example;

Now, in the app.tsx file, add the example component like so.

 
import React from 'react';
import logo from './logo.svg';
import './App.css';
import Example from './components/Example';

function App() {
  return (
    <div className="App">
      <header className="App-header">
        <Example />
        <img src={logo} className="App-logo" alt="logo" />
        <p>
          Edit <code>src/App.tsx</code> and save to reload.
        </p>
        <a
          className="App-link"
          href="https://reactjs.org"
          target="_blank"
          rel="noopener noreferrer"
        >
          Learn React
        </a>
      </header>
    </div>
  );
}

export default App;

After completing those steps, our project is set up, and we’re ready to move on to creating the environment file.

Create the Environment File

To start, we’ll add a new file name .env to the project root folder. example-app/.env. This will be where we’ll create key-value pairs as variables.

One important thing to remember is that the key will need to be prefaced with REACT_APP_. React will ignore anything without it, except NODE_ENV. Anyone can inspect the application file because the environment variables are embedded, do not put any secrets or passwords in your file.

In the file add:

REACT_APP_EXAMPLE=Awesome Title

To access the environment variables in your code, you will need to call process.env.REACT_APP_EXAMPLE. To do that, change the following line from our Example.tsx component from:

<h1>An Okay Title</h1>
<h1>{process.env.REACT_APP_EXAMPLE}</h1>

Node will inject the values at runtime, so any changes to a .env file will require you to restart the development server before the change will take effect.

With these steps out of the way, you should now see Awesome Title when viewing the app.

Custom Hook

One of the things I like the most about React is that it feels more object-oriented. This step isn’t really necessary, but it abstracts the configuration with a custom React hook keeping the process.env variables in one place. Since we are using TypeScript, this allows us to define a model and ensure that we are asking for the correct thing.

We should first create a key-value pair model to be used with the custom React hook. Create a new folder under src called Common. Then add a new file called ApplicationConfiguration.ts to the new folder with the following code:

export default interface ApplicationConfiguration {
    [key: string] : string
}

Create another file in that folder called UseConfiguration.tsx; this will be the hook. Add the following code:

import { useEffect, useState } from "react";
import ApplicationConfiguration from "./ApplicationConfiguration";

export const useConfiguration = (): [
    ApplicationConfiguration,
    React.Dispatch<ApplicationConfiguration>
  ] => {
    const [config, setConfig] = useState<ApplicationConfiguration>({});
   
    useEffect(() => {
      setConfig({ exampleTitle: process.env.REACT_APP_EXAMPLE ?? "" });
    }, []);
   
    return [config, setConfig];
  };

Then, when you want to use the configuration, you can import the hook and use it in the component that needs it. Change the Example.tsx component to use the custom hook:

import React, { useEffect, useState } from "react";
import { useConfiguration } from "../common/useConfiguration";

const Example: React.FC = () => {
  const [config] = useConfiguration();
  const [title, setTitle] = useState<string>("");

  useEffect(() => {
    if(config.exampleTitle !== undefined){
        setTitle(config.exampleTitle)
    }
  }, [config])

  return (
    <div>
      <h1>{title}</h1>
    </div>
  );
};
export default Example;

If you have a useEffect in your React component that is fetching with empty parameters, then there’s a chance that it might fire before the useConfiguration hook has fired.

You can avoid this by adding the config to the useEffect and making sure there is a value before fetching. The useEffect will monitor the config variable, and anytime it changes, it will fire.

If you run this in debug mode with a breakpoint on the IF statement, you’ll see the first time it breaks – the config is empty and the exampleTitle is undefined. The second time it breaks, the useConfiguration has completed and the config has a value.

Different Environments

If you want to configure another environment, it’s really a matter of copying the .env file and pasting it. Then, you can rename it something like .env.qa and modify the value pairs to what should be in the new environment.

REACT_APP_EXAMPLE=Awesome QA Title

When you build or start the code, use env-cmd to tell Node which values to use.

First, add yarn/npm in the env-cmd library.

yarn add  env-cmd

Next, add the following to your package.json file under “scripts.”

"start:qa": "env-cmd -f .env.qa react-scripts start",
 "build:qa": "env-cmd -f .env.qa react-scripts build"

Once you’ve finished, it should look like this:

"scripts": {
    "start": "react-scripts start",
    "build": "react-scripts build",
    "start:qa": "env-cmd -f .env.qa react-scripts start",
    "build:qa": "env-cmd -f .env.qa react-scripts build",
    "test": "react-scripts test",
    "eject": "react-scripts eject"
  }

Then if you want to test this you can run yarn start:qa to see that now the title says “Awesome QA Title.”

If you want to configure your application to test locally, add .env.local, and Node will replace the values from the from the .env file with those in the .env.local. This file is added automatically to the .gitignore, so you won’t check it in and maybe accidentally use the wrong variables.

Wrapping Up …

In conclusion, we learned how to add environment variables to a React application and use a custom hook to encapsulate them. We also showed how to configure your React project for multiple environments.

This method will allow us to embed any value that may be different in each environment without having to find all of the places that it is used in code, which will reduce the chance for mistakes in your code. Ultimately, this will save valuable time and effort!


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK