DEV Community

Mohammad Waseem
Mohammad Waseem

Posted on

React Tips: Keep Development Isolated from Real Data

React Tips: Keep Development Isolated from Real Data

The Problem

While building a React app under velocity, it's tempting to hook up real backend services straight away. That has three side‑effects you’ll quickly notice:

  1. API keys creep into your code, increasing the attack surface.
  2. Tests that hit prod endpoints become flaky and may change real data.
  3. Your local machine ends up pulling real logs, audit trails, and potentially sensitive user information.

You can avoid all of that by treating each environment as a sandbox. A sandbox boundary means that during development, your app never touches production data or secrets, and the production system is forced to interact only with its own curated dataset.

Why it matters

Data breaches have gotten more expensive and more frequent. In 2026, the average cost of a breach was reported at $10.5 million for sizable enterprises, and the median recovery time hit 200 days. A single compromised development environment can expose thousands of personally identifiable records—or worse, business‑critical secrets—through accidental commits or exposed API keys. Those 200 days of downtime, not to mention legal penalties and customer churn, quantify the cost of losing that isolation.

The Solution – Step‑by‑Step

Below is a practical, repeatable approach that fits into a React + TypeScript workflow. It’s built around three pillars: environment‑tainted secrets, mocked data, and a second‑chance filter to catch accidental leaks.


1. Set up separate environment files

Create .env.development, .env.staging, and .env.production. Each holds the entry‑points for your API server and any third‑party services.

# .env.development
REACT_APP_API_ENDPOINT=http://localhost:4000/api
REACT_APP_THIRD_PARTY_KEY=dev‑dummy‑key

# .env.production
REACT_APP_API_ENDPOINT=https://api.myapp.com
REACT_APP_THIRD_PARTY_KEY=$(cat /run/secrets/third_party_key)
Enter fullscreen mode Exit fullscreen mode

Use dotenv at the top of your entry file so the correct file is picked up:

import 'dotenv/config';
Enter fullscreen mode Exit fullscreen mode

React scripts automatically load the right file based on npm run start or npm run build.


2. Mock every real endpoint

Next, pick a mocking strategy that fits your stack.

Tool Pros Cons
MirageJS Runs in the browser; trivial for fetch/XHR. Does not test against actual server logic.
Mock Service Worker (MSW) Intercepts network at the service‑worker layer; works with fetch, axios, GraphQL. Requires polyfill for older browsers.
JSON Server Quick static REST API for demo data. Not real‑time schema enforcement.

A lightweight beginner pick is MSW. Install it:

npm i msw --save-dev
Enter fullscreen mode Exit fullscreen mode

Create src/mocks/handlers.ts:

import { rest } from 'msw';

export const handlers = [
  rest.get('/api/user', (req, res, ctx) => {
    return res(
      ctx.status(200),
      ctx.json({ id: 1, name: 'Alice', email: 'alice@demo.com' })
    );
  }),
];
Enter fullscreen mode Exit fullscreen mode

Initialize it in src/mocks/browser.ts:

import { setupWorker } from 'msw';
import { handlers } from './handlers';

export const worker = setupWorker(...handlers);
Enter fullscreen mode Exit fullscreen mode

Then, in index.tsx:

if (process.env.NODE_ENV === 'development') {
  const { worker } = require('./mocks/browser');
  worker.start();
}
Enter fullscreen mode Exit fullscreen mode

All fetches to /api/* will hit the mock while you’re local, and the production build will never load it.


3. Keep secrets safe

Avoid blanket “add every env var to your repo” habit. Store any developer‑only key in the .env.development file and never commit it. Use the .gitignore entry:

.env*
Enter fullscreen mode Exit fullscreen mode

For secrets that the production build needs, rely on your CI system’s secret store:

# GitHub Actions example
steps:
- name: Publish
  env:
    THIRD_PARTY_KEY: ${{ secrets.IMAGE_REPO_KEY }}
    ...
Enter fullscreen mode Exit fullscreen mode

On local machines, fetch those from a local vault or keep them in ~/.env.production with manual sync to CI.


4. Add a “real‑data guard”

Add a simple runtime check in dev mode that throws if the app ever attempts a real HTTP request. This is a smoke‑test guard:

if (process.env.NODE_ENV === 'development') {
  const originalFetch = window.fetch;
  window.fetch = (...args) => {
    const url = args[0] as string;
    if (!url.includes('localhost') && !url.includes('127.0.0.1')) {
      throw new Error(`Blocked real request to ${url}`);
    }
    return originalFetch.apply(this, args);
  };
}
Enter fullscreen mode Exit fullscreen mode

It’s an extra safety net that can catch accidental URL typos pointing to prod.


5. Validate with CI

Add a lint rule or precommit hook that scans for environment variables like REACT_APP_API_ENDPOINT pointing to a production domain in the dev branch. Tools like eslint-plugin-no-proxy can help detect if you’ve accidentally set the wrong endpoint.


Wrap‑up

By systematically hiding secrets behind environment files, replacing every real endpoint with a sandbox mock, and installing runtime guards, you keep your React dev environment livable and your production data hostage‑free. In 2026, breach costs have made this more than a nice‑to‑have; it’s a business‑critical practice. Happy coding and stay safe!

🛠️ The Tool I Use

    For generating clean test data and disposable emails for these workflows, I personally use [TempoMail USA](https://tempomailusa.com). It’s fast, has an API-like feel, and keeps my production data clean.
Enter fullscreen mode Exit fullscreen mode

Top comments (0)