Hiding Api Key By Adding Custom Environment Variables

Posted on July 17, 2026 by Vishesh Namdev
Python C C++ Javascript React JS
Hiding API Key in React by Adding Custom Environment Variables

Hiding API Key by Adding Custom Environment Variables 🔐🔑 So far, we've been calling our News API with the API key written directly inside our code. That's a problem — if we push this code to GitHub, anyone can see our secret key in the commit history. In this tutorial, we'll learn the right way to hide sensitive values like API keys using environment variables in a React app.

In this tutorial, we will learn:

  • What environment variables are and why they matter for security
  • Creating a .env file in a React project
  • Why React environment variables must start with REACT_APP_
  • Reading environment variables using process.env
  • Adding .env to .gitignore so it never reaches GitHub
  • Restarting the dev server so new variables take effect
  • ---

    What Are Environment Variables?

    An environment variable is a value that lives outside your source code, usually in a special file, and gets injected into your app at build or run time. Instead of hardcoding a secret like an API key directly in News.js, we store it in a .env file that never gets shared publicly. This keeps sensitive data safe even if your code is open source.

    ---

    Step 1: Create a .env File

    In the root of your React project (same level as package.json), create a new file named .env.

    REACT_APP_NEWS_API_KEY=your_actual_api_key_here

    Important: In Create React App projects, every custom environment variable must start with REACT_APP_, otherwise React will ignore it completely.

    ---

    Step 2: Add .env to .gitignore

    We never want to push our .env file to GitHub. Open (or create) the .gitignore file in your project root and add this line:

    # Environment variables
    .env

    If you already committed .env before adding this line, remove it from Git tracking with git rm --cached .env and commit again.

    ---

    Step 3: Access the API Key with process.env

    Now, in News.js, replace the hardcoded key with a reference to process.env.REACT_APP_NEWS_API_KEY.

    fetchArticles = () => {
      this.setState({ loading: true });
     
      const apiKey = process.env.REACT_APP_NEWS_API_KEY;
      const url = `https://newsapi.org/v2/top-headlines?country=us&page=${this.state.page}&pageSize=${this.state.pageSize}&apiKey=${apiKey}`;
     
      fetch(url)
        .then((response) => response.json())
        .then((data) => {
          this.setState({
            articles: data.articles,
            loading: false,
          });
        });
    };
    ---

    Step 4: Restart the Development Server

    React only reads .env values when the dev server starts. If your app is already running, stop it and run npm start again — otherwise your new environment variable will show up as undefined.

    npm start
    ---

    Step 5: Full Updated News.js

    Here is the complete News.js file with the API key now loaded securely from an environment variable instead of being hardcoded.

    import React, { Component } from "react";
    import NewsItem from "./NewsItem";
    import Spinner from "./Spinner";
     
    export class News extends Component {
     
      static defaultProps = {
        pageSize: 6,
        totalResults: 30,
      };
     
      state = {
        articles: [],
        page: 1,
        loading: false,
        pageSize: this.props.pageSize,
      };
     
      fetchArticles = () => {
        this.setState({ loading: true });
     
        const apiKey = process.env.REACT_APP_NEWS_API_KEY;
        const url = `https://newsapi.org/v2/top-headlines?country=us&page=${this.state.page}&pageSize=${this.state.pageSize}&apiKey=${apiKey}`;
     
        fetch(url)
          .then((response) => response.json())
          .then((data) => {
            this.setState({
              articles: data.articles,
              loading: false,
            });
          });
      };
     
      componentDidMount() {
        this.fetchArticles();
      }
     
      handlePrevClick = () => {
        this.setState({ page: this.state.page - 1 }, () => {
          this.fetchArticles();
        });
      };
     
      handleNextClick = () => {
        this.setState({ page: this.state.page + 1 }, () => {
          this.fetchArticles();
        });
      };
     
      handlePageSizeChange = (e) => {
        const newSize = Number(e.target.value);
        this.setState({ pageSize: newSize, page: 1 }, () => {
          this.fetchArticles();
        });
      };
     
      render() {
        const { totalResults } = this.props;
        const { page, pageSize, articles, loading } = this.state;
     
        return (
          <div className="container my-4">
            <h2 className="text-center mb-4">Welcome to News App 📰</h2>
     
            <div className="d-flex justify-content-end mb-3">
              <label className="me-2 align-self-center fw-bold">Articles per page:</label>
              <select
                className="form-select w-auto"
                value={pageSize}
                onChange={this.handlePageSizeChange}
              >
                <option value="3">3</option>
                <option value="6">6</option>
                <option value="9">9</option>
                <option value="12">12</option>
              </select>
            </div>
     
            {loading ? (
              <Spinner />
            ) : (
              articles.map((article, index) => (
                <NewsItem
                  key={index}
                  title={article.title}
                  description={article.description}
                  imageUrl={article.urlToImage}
                  newsUrl={article.url}
                />
              ))
            )}
     
            <div className="d-flex justify-content-between my-4">
              <button
                className="btn btn-warning"
                onClick={this.handlePrevClick}
                disabled={loading || page <= 1}
              >
                &larr; Previous
              </button>
     
              <span className="align-self-center fw-bold">
                Page {page} of {Math.ceil(totalResults / pageSize)}
              </span>
     
              <button
                className="btn btn-warning"
                onClick={this.handleNextClick}
                disabled={loading || page >= Math.ceil(totalResults / pageSize)}
              >
                Next &rarr;
              </button>
            </div>
     
          </div>
        );
      }
    }
     
    export default News;
    ---

    Environment Variable Quick Reference

    File / Code Purpose Notes
    .env Stores the actual API key value locally Must sit in the project root, never committed to Git
    REACT_APP_ prefix Tells Create React App to expose the variable to the frontend build Variables without this prefix are ignored
    process.env.REACT_APP_NEWS_API_KEY Reads the key inside your component code Undefined until the dev server is restarted after edits
    .gitignore Prevents .env from being pushed to GitHub Add .env as its own line
    ---

    Features and Learnings:-

  • Understood what environment variables are and why hiding API keys matters.
  • Created a .env file to store the News API key outside of source code.
  • Learned why React requires the REACT_APP_ prefix for custom variables.
  • Accessed the hidden key safely using process.env.
  • Protected the key from GitHub by adding .env to .gitignore.
  • Restarted the dev server so environment changes took effect.
  • Connected the News App to the live News API using the hidden key.
  • 📢 Important Note 📢

    How did you feel about this post?

    😍 🙂 😐 😕 😡

    Was this helpful?

    👍 👎